kbdcontrol.c revision 39047
1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#ifndef lint 30static const char rcsid[] = 31 "$Id: kbdcontrol.c,v 1.18 1998/09/04 10:15:48 yokota Exp $"; 32#endif /* not lint */ 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 <machine/console.h> 41#include "path.h" 42#include "lex.h" 43 44char ctrl_names[32][4] = { 45 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 46 "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 47 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 48 "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 49 }; 50 51char acc_names[15][5] = { 52 "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 53 "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 54 "dcar", 55 }; 56 57char acc_names_u[15][5] = { 58 "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 59 "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 60 "DCAR", 61 }; 62 63char fkey_table[96][MAXFK] = { 64/* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 65/* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 66/* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 67/* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 68/* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 69/* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 70/* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 71/* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 72/* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 73/* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 74/* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 75/* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 76/* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 77/* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 78/* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 79/* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 80/* 65-68 */ "" , "" , "" , "" , 81/* 69-72 */ "" , "" , "" , "" , 82/* 73-76 */ "" , "" , "" , "" , 83/* 77-80 */ "" , "" , "" , "" , 84/* 81-84 */ "" , "" , "" , "" , 85/* 85-88 */ "" , "" , "" , "" , 86/* 89-92 */ "" , "" , "" , "" , 87/* 93-96 */ "" , "" , "" , "" , 88 }; 89 90const int delays[] = {250, 500, 750, 1000}; 91const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 92 68, 76, 84, 92, 100, 110, 118, 126, 93 136, 152, 168, 184, 200, 220, 236, 252, 94 272, 304, 336, 368, 400, 440, 472, 504}; 95const int ndelays = (sizeof(delays) / sizeof(int)); 96const int nrepeats = (sizeof(repeats) / sizeof(int)); 97int hex = 0; 98int number; 99char letter; 100int token; 101 102static void usage __P((void)); 103 104char * 105nextarg(int ac, char **av, int *indp, int oc) 106{ 107 if (*indp < ac) 108 return(av[(*indp)++]); 109 warnx("option requires two arguments -- %c", oc); 110 usage(); 111 return(""); 112} 113 114 115char * 116mkfullname(const char *s1, const char *s2, const char *s3) 117{ 118 static char *buf = NULL; 119 static int bufl = 0; 120 int f; 121 122 f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 123 if (f > bufl) 124 if (buf) 125 buf = (char *)realloc(buf, f); 126 else 127 buf = (char *)malloc(f); 128 if (!buf) { 129 bufl = 0; 130 return(NULL); 131 } 132 133 bufl = f; 134 strcpy(buf, s1); 135 strcat(buf, s2); 136 strcat(buf, s3); 137 return(buf); 138} 139 140 141int 142get_entry() 143{ 144 switch ((token = yylex())) { 145 case TNOP: 146 return NOP | 0x100; 147 case TLSH: 148 return LSH | 0x100; 149 case TRSH: 150 return RSH | 0x100; 151 case TCLK: 152 return CLK | 0x100; 153 case TNLK: 154 return NLK | 0x100; 155 case TSLK: 156 return SLK | 0x100; 157 case TBTAB: 158 return BTAB | 0x100; 159 case TLALT: 160 return LALT | 0x100; 161 case TLCTR: 162 return LCTR | 0x100; 163 case TNEXT: 164 return NEXT | 0x100; 165 case TRCTR: 166 return RCTR | 0x100; 167 case TRALT: 168 return RALT | 0x100; 169 case TALK: 170 return ALK | 0x100; 171 case TASH: 172 return ASH | 0x100; 173 case TMETA: 174 return META | 0x100; 175 case TRBT: 176 return RBT | 0x100; 177 case TDBG: 178 return DBG | 0x100; 179 case TSUSP: 180 return SUSP | 0x100; 181 case TSPSC: 182 return SPSC | 0x100; 183 case TACC: 184 if (ACC(number) > L_ACC) 185 return -1; 186 return ACC(number) | 0x100; 187 case TFUNC: 188 if (F(number) > L_FN) 189 return -1; 190 return F(number) | 0x100; 191 case TSCRN: 192 if (S(number) > L_SCR) 193 return -1; 194 return S(number) | 0x100; 195 case TLET: 196 return (unsigned char)letter; 197 case TNUM: 198 if (number < 0 || number > 255) 199 return -1; 200 return number; 201 default: 202 return -1; 203 } 204} 205 206int 207get_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap) 208{ 209 int c; 210 211 yyin = fd; 212 213 if (token < 0) 214 token = yylex(); 215 switch (token) { 216 case TNUM: 217 c = get_key_definition_line(keymap); 218 if (c < 0) 219 errx(1, "invalid key definition"); 220 if (c > keymap->n_keys) 221 keymap->n_keys = c; 222 break; 223 case TACC: 224 c = get_accent_definition_line(accentmap); 225 if (c < 0) 226 errx(1, "invalid accent key definition"); 227 if (c > accentmap->n_accs) 228 accentmap->n_accs = c; 229 break; 230 case 0: 231 /* EOF */ 232 return -1; 233 default: 234 errx(1, "illegal definition line"); 235 } 236 return c; 237} 238 239int 240get_key_definition_line(keymap_t *map) 241{ 242 int i, def, scancode; 243 244 /* check scancode number */ 245 if (number < 0 || number >= NUM_KEYS) 246 return -1; 247 scancode = number; 248 249 /* get key definitions */ 250 map->key[scancode].spcl = 0; 251 for (i=0; i<NUM_STATES; i++) { 252 if ((def = get_entry()) == -1) 253 return -1; 254 if (def & 0x100) 255 map->key[scancode].spcl |= (0x80 >> i); 256 map->key[scancode].map[i] = def & 0xFF; 257 } 258 /* get lock state key def */ 259 if ((token = yylex()) != TFLAG) 260 return -1; 261 map->key[scancode].flgs = number; 262 token = yylex(); 263 return (scancode + 1); 264} 265 266int 267get_accent_definition_line(accentmap_t *map) 268{ 269 int accent; 270 int c1, c2; 271 int i; 272 273 if (ACC(number) < F_ACC || ACC(number) > L_ACC) 274 /* number out of range */ 275 return -1; 276 accent = number; 277 if (map->acc[accent].accchar != 0) { 278 /* this entry has already been defined before! */ 279 errx(1, "duplicated accent key definition"); 280 } 281 282 switch ((token = yylex())) { 283 case TLET: 284 map->acc[accent].accchar = letter; 285 break; 286 case TNUM: 287 map->acc[accent].accchar = number; 288 break; 289 default: 290 return -1; 291 } 292 293 for (i = 0; (token = yylex()) == '(';) { 294 switch ((token = yylex())) { 295 case TLET: 296 c1 = letter; 297 break; 298 case TNUM: 299 c1 = number; 300 break; 301 default: 302 return -1; 303 } 304 switch ((token = yylex())) { 305 case TLET: 306 c2 = letter; 307 break; 308 case TNUM: 309 c2 = number; 310 break; 311 default: 312 return -1; 313 } 314 if ((token = yylex()) != ')') 315 return -1; 316 if (i >= NUM_ACCENTCHARS) { 317 warnx("too many accented characters, ignored"); 318 continue; 319 } 320 map->acc[accent].map[i][0] = c1; 321 map->acc[accent].map[i][1] = c2; 322 ++i; 323 } 324 return (accent + 1); 325} 326 327void 328print_entry(FILE *fp, int value) 329{ 330 int val = value & 0xFF; 331 332 switch (value) { 333 case NOP | 0x100: 334 fprintf(fp, " nop "); 335 break; 336 case LSH | 0x100: 337 fprintf(fp, " lshift"); 338 break; 339 case RSH | 0x100: 340 fprintf(fp, " rshift"); 341 break; 342 case CLK | 0x100: 343 fprintf(fp, " clock "); 344 break; 345 case NLK | 0x100: 346 fprintf(fp, " nlock "); 347 break; 348 case SLK | 0x100: 349 fprintf(fp, " slock "); 350 break; 351 case BTAB | 0x100: 352 fprintf(fp, " btab "); 353 break; 354 case LALT | 0x100: 355 fprintf(fp, " lalt "); 356 break; 357 case LCTR | 0x100: 358 fprintf(fp, " lctrl "); 359 break; 360 case NEXT | 0x100: 361 fprintf(fp, " nscr "); 362 break; 363 case RCTR | 0x100: 364 fprintf(fp, " rctrl "); 365 break; 366 case RALT | 0x100: 367 fprintf(fp, " ralt "); 368 break; 369 case ALK | 0x100: 370 fprintf(fp, " alock "); 371 break; 372 case ASH | 0x100: 373 fprintf(fp, " ashift"); 374 break; 375 case META | 0x100: 376 fprintf(fp, " meta "); 377 break; 378 case RBT | 0x100: 379 fprintf(fp, " boot "); 380 break; 381 case DBG | 0x100: 382 fprintf(fp, " debug "); 383 break; 384 case SUSP | 0x100: 385 fprintf(fp, " susp "); 386 break; 387 case SPSC | 0x100: 388 fprintf(fp, " saver "); 389 break; 390 default: 391 if (value & 0x100) { 392 if (val >= F_FN && val <= L_FN) 393 fprintf(fp, " fkey%02d", val - F_FN + 1); 394 else if (val >= F_SCR && val <= L_SCR) 395 fprintf(fp, " scr%02d ", val - F_SCR + 1); 396 else if (val >= F_ACC && val <= L_ACC) 397 fprintf(fp, " %-6s", acc_names[val - F_ACC]); 398 else if (hex) 399 fprintf(fp, " 0x%02x ", val); 400 else 401 fprintf(fp, " %3d ", val); 402 } 403 else { 404 if (val < ' ') 405 fprintf(fp, " %s ", ctrl_names[val]); 406 else if (val == 127) 407 fprintf(fp, " del "); 408 else if (isascii(val) && isprint(val)) 409 fprintf(fp, " '%c' ", val); 410 else if (hex) 411 fprintf(fp, " 0x%02x ", val); 412 else 413 fprintf(fp, " %3d ", val); 414 } 415 } 416} 417 418 419void 420print_key_definition_line(FILE *fp, int scancode, struct key_t *key) 421{ 422 int i; 423 424 /* print scancode number */ 425 if (hex) 426 fprintf(fp, " 0x%02x ", scancode); 427 else 428 fprintf(fp, " %03d ", scancode); 429 430 /* print key definitions */ 431 for (i=0; i<NUM_STATES; i++) { 432 if (key->spcl & (0x80 >> i)) 433 print_entry(fp, key->map[i] | 0x100); 434 else 435 print_entry(fp, key->map[i]); 436 } 437 438 /* print lock state key def */ 439 switch (key->flgs) { 440 case 0: 441 fprintf(fp, " O\n"); 442 break; 443 case 1: 444 fprintf(fp, " C\n"); 445 break; 446 case 2: 447 fprintf(fp, " N\n"); 448 break; 449 case 3: 450 fprintf(fp, " B\n"); 451 break; 452 } 453} 454 455void 456print_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 457{ 458 int c; 459 int i; 460 461 if (key->accchar == 0) 462 return; 463 464 /* print accent number */ 465 fprintf(fp, " %-6s", acc_names[accent]); 466 if (isascii(key->accchar) && isprint(key->accchar)) 467 fprintf(fp, "'%c' ", key->accchar); 468 else if (hex) 469 fprintf(fp, "0x%02x ", key->accchar); 470 else 471 fprintf(fp, "%03d ", key->accchar); 472 473 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 474 c = key->map[i][0]; 475 if (c == 0) 476 break; 477 if ((i > 0) && ((i % 4) == 0)) 478 fprintf(fp, "\n "); 479 if (isascii(c) && isprint(c)) 480 fprintf(fp, "( '%c' ", c); 481 else if (hex) 482 fprintf(fp, "(0x%02x ", c); 483 else 484 fprintf(fp, "( %03d ", c); 485 c = key->map[i][1]; 486 if (isascii(c) && isprint(c)) 487 fprintf(fp, "'%c' ) ", c); 488 else if (hex) 489 fprintf(fp, "0x%02x) ", c); 490 else 491 fprintf(fp, "%03d ) ", c); 492 } 493 fprintf(fp, "\n"); 494} 495 496void 497dump_entry(int value) 498{ 499 if (value & 0x100) { 500 value &= 0x00ff; 501 switch (value) { 502 case NOP: 503 printf(" NOP, "); 504 break; 505 case LSH: 506 printf(" LSH, "); 507 break; 508 case RSH: 509 printf(" RSH, "); 510 break; 511 case CLK: 512 printf(" CLK, "); 513 break; 514 case NLK: 515 printf(" NLK, "); 516 break; 517 case SLK: 518 printf(" SLK, "); 519 break; 520 case BTAB: 521 printf(" BTAB, "); 522 break; 523 case LALT: 524 printf(" LALT, "); 525 break; 526 case LCTR: 527 printf(" LCTR, "); 528 break; 529 case NEXT: 530 printf(" NEXT, "); 531 break; 532 case RCTR: 533 printf(" RCTR, "); 534 break; 535 case RALT: 536 printf(" RALT, "); 537 break; 538 case ALK: 539 printf(" ALK, "); 540 break; 541 case ASH: 542 printf(" ASH, "); 543 break; 544 case META: 545 printf(" META, "); 546 break; 547 case RBT: 548 printf(" RBT, "); 549 break; 550 case DBG: 551 printf(" DBG, "); 552 break; 553 case SUSP: 554 printf(" SUSP, "); 555 break; 556 case SPSC: 557 printf(" SPSC, "); 558 break; 559 default: 560 if (value >= F_FN && value <= L_FN) 561 printf(" F(%2d),", value - F_FN + 1); 562 else if (value >= F_SCR && value <= L_SCR) 563 printf(" S(%2d),", value - F_SCR + 1); 564 else if (value >= F_ACC && value <= L_ACC) 565 printf(" %-4s, ", acc_names_u[value - F_ACC]); 566 else 567 printf(" 0x%02X, ", value); 568 break; 569 } 570 } else if (value == '\'') { 571 printf(" '\\'', "); 572 } else if (value == '\\') { 573 printf(" '\\\\', "); 574 } else if (isascii(value) && isprint(value)) { 575 printf(" '%c', ", value); 576 } else { 577 printf(" 0x%02X, ", value); 578 } 579} 580 581void 582dump_key_definition(char *name, keymap_t *keymap) 583{ 584 int i, j; 585 586 printf("static keymap_t keymap_%s = { 0x%02x, {\n", 587 name, (unsigned)keymap->n_keys); 588 printf( 589"/* alt\n" 590" * scan cntrl alt alt cntrl\n" 591" * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 592" * ---------------------------------------------------------------------------\n" 593" */\n"); 594 for (i = 0; i < keymap->n_keys; i++) { 595 printf("/*%02x*/{{", i); 596 for (j = 0; j < NUM_STATES; j++) { 597 if (keymap->key[i].spcl & (0x80 >> j)) 598 dump_entry(keymap->key[i].map[j] | 0x100); 599 else 600 dump_entry(keymap->key[i].map[j]); 601 } 602 printf("}, 0x%02X,0x%02X },\n", 603 (unsigned)keymap->key[i].spcl, 604 (unsigned)keymap->key[i].flgs); 605 } 606 printf("} };\n\n"); 607} 608 609void 610dump_accent_definition(char *name, accentmap_t *accentmap) 611{ 612 int i, j; 613 int c; 614 615 printf("static accentmap_t accentmap_%s = { %d", 616 name, accentmap->n_accs); 617 if (accentmap->n_accs <= 0) { 618 printf(" };\n\n"); 619 return; 620 } 621 printf(", {\n"); 622 for (i = 0; i < NUM_DEADKEYS; i++) { 623 printf(" /* %s=%d */\n {", acc_names[i], i); 624 c = accentmap->acc[i].accchar; 625 if (c == '\'') 626 printf(" '\\'', {"); 627 else if (c == '\\') 628 printf(" '\\\\', {"); 629 else if (isascii(c) && isprint(c)) 630 printf(" '%c', {", c); 631 else if (c == 0) { 632 printf(" 0x00 }, \n"); 633 continue; 634 } else 635 printf(" 0x%02x, {", c); 636 for (j = 0; j < NUM_ACCENTCHARS; j++) { 637 c = accentmap->acc[i].map[j][0]; 638 if (c == 0) 639 break; 640 if ((j > 0) && ((j % 4) == 0)) 641 printf("\n\t "); 642 if (isascii(c) && isprint(c)) 643 printf(" { '%c',", c); 644 else 645 printf(" { 0x%02x,", c); 646 printf("0x%02x },", accentmap->acc[i].map[j][1]); 647 } 648 printf(" }, },\n"); 649 } 650 printf("} };\n\n"); 651} 652 653void 654load_keymap(char *opt, int dumponly) 655{ 656 keymap_t keymap; 657 accentmap_t accentmap; 658 FILE *fd; 659 int i; 660 char *name, *cp; 661 char *prefix[] = {"", "", KEYMAP_PATH, KEYMAP_PATH, NULL}; 662 char *postfix[] = {"", ".kbd", "", ".kbd"}; 663 664 for (i=0; prefix[i]; i++) { 665 name = mkfullname(prefix[i], opt, postfix[i]); 666 if ((fd = fopen(name, "r"))) 667 break; 668 } 669 if (fd == NULL) { 670 warn("keymap file not found"); 671 return; 672 } 673 memset(&keymap, 0, sizeof(keymap)); 674 memset(&accentmap, 0, sizeof(accentmap)); 675 token = -1; 676 while (1) { 677 if (get_definition_line(fd, &keymap, &accentmap) < 0) 678 break; 679 } 680 if (dumponly) { 681 /* fix up the filename to make it a valid C identifier */ 682 for (cp = opt; *cp; cp++) 683 if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 684 printf("/*\n" 685 " * Automatically generated from %s.\n" 686 " * DO NOT EDIT!\n" 687 " */\n", name); 688 dump_key_definition(opt, &keymap); 689 dump_accent_definition(opt, &accentmap); 690 return; 691 } 692 if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 693 warn("setting keymap"); 694 fclose(fd); 695 return; 696 } 697 if ((accentmap.n_accs > 0) 698 && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 699 warn("setting accentmap"); 700 fclose(fd); 701 return; 702 } 703} 704 705void 706print_keymap() 707{ 708 keymap_t keymap; 709 accentmap_t accentmap; 710 int i; 711 712 if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 713 err(1, "getting keymap"); 714 if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 715 memset(&accentmap, 0, sizeof(accentmap)); 716 printf( 717"# alt\n" 718"# scan cntrl alt alt cntrl lock\n" 719"# code base shift cntrl shift alt shift cntrl shift state\n" 720"# ------------------------------------------------------------------\n" 721 ); 722 for (i=0; i<keymap.n_keys; i++) 723 print_key_definition_line(stdout, i, &keymap.key[i]); 724 725 printf("\n"); 726 for (i = 0; i < NUM_DEADKEYS; i++) 727 print_accent_definition_line(stdout, i, &accentmap.acc[i]); 728 729} 730 731 732void 733load_default_functionkeys() 734{ 735 fkeyarg_t fkey; 736 int i; 737 738 for (i=0; i<NUM_FKEYS; i++) { 739 fkey.keynum = i; 740 strcpy(fkey.keydef, fkey_table[i]); 741 fkey.flen = strlen(fkey_table[i]); 742 if (ioctl(0, SETFKEY, &fkey) < 0) 743 warn("setting function key"); 744 } 745} 746 747void 748set_functionkey(char *keynumstr, char *string) 749{ 750 fkeyarg_t fkey; 751 752 if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 753 load_default_functionkeys(); 754 return; 755 } 756 fkey.keynum = atoi(keynumstr); 757 if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 758 warnx("function key number must be between 1 and %d", 759 NUM_FKEYS); 760 return; 761 } 762 if ((fkey.flen = strlen(string)) > MAXFK) { 763 warnx("function key string too long (%d > %d)", 764 fkey.flen, MAXFK); 765 return; 766 } 767 strcpy(fkey.keydef, string); 768 fkey.keynum -= 1; 769 if (ioctl(0, SETFKEY, &fkey) < 0) 770 warn("setting function key"); 771} 772 773 774void 775set_bell_values(char *opt) 776{ 777 int bell, duration, pitch; 778 779 bell = 0; 780 if (!strncmp(opt, "quiet.", 6)) { 781 bell = 2; 782 opt += 6; 783 } 784 if (!strcmp(opt, "visual")) 785 bell |= 1; 786 else if (!strcmp(opt, "normal")) 787 duration = 5, pitch = 800; 788 else { 789 char *v1; 790 791 bell = 0; 792 duration = strtol(opt, &v1, 0); 793 if ((duration < 0) || (*v1 != '.')) 794 goto badopt; 795 opt = ++v1; 796 pitch = strtol(opt, &v1, 0); 797 if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 798badopt: 799 warnx("argument to -b must be DURATION.PITCH"); 800 return; 801 } 802 if (pitch != 0) 803 pitch = 1193182 / pitch; /* in Hz */ 804 duration /= 10; /* in 10 m sec */ 805 } 806 807 ioctl(0, CONS_BELLTYPE, &bell); 808 if ((bell & ~2) == 0) 809 fprintf(stderr, "[=%d;%dB", pitch, duration); 810} 811 812 813void 814set_keyrates(char *opt) 815{ 816 int repeat; 817 int delay; 818 819 if (!strcmp(opt, "slow")) 820 delay = 3, repeat = 31; 821 else if (!strcmp(opt, "normal")) 822 delay = 1, repeat = 15; 823 else if (!strcmp(opt, "fast")) 824 delay = repeat = 0; 825 else { 826 int n; 827 char *v1; 828 829 delay = strtol(opt, &v1, 0); 830 if ((delay < 0) || (*v1 != '.')) 831 goto badopt; 832 opt = ++v1; 833 repeat = strtol(opt, &v1, 0); 834 if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 835badopt: 836 warnx("argument to -r must be delay.repeat"); 837 return; 838 } 839 for (n = 0; n < ndelays - 1; n++) 840 if (delay <= delays[n]) 841 break; 842 delay = n; 843 for (n = 0; n < nrepeats - 1; n++) 844 if (repeat <= repeats[n]) 845 break; 846 repeat = n; 847 } 848 849 if (ioctl(0, KDSETRAD, (delay << 5) | repeat) < 0) 850 warn("setting keyboard rate"); 851} 852 853 854void 855set_history(char *opt) 856{ 857 int size; 858 859 size = atoi(opt); 860 if ((*opt == '\0') || size < 0) { 861 warnx("argument must be a positive number"); 862 return; 863 } 864 if (ioctl(0, CONS_HISTORY, &size) == -1) 865 warn("setting history buffer size"); 866} 867 868 869static void 870usage() 871{ 872 fprintf(stderr, "%s\n%s\n%s\n", 873"usage: kbdcontrol [-dFx] [-b duration.pitch | [quiet.]belltype]", 874" [-r delay.repeat | speed] [-l mapfile] [-f # string]", 875" [-h size] [-L mapfile]"); 876 exit(1); 877} 878 879 880void 881main(int argc, char **argv) 882{ 883 int opt; 884 885 while((opt = getopt(argc, argv, "b:df:h:Fl:L:r:x")) != -1) 886 switch(opt) { 887 case 'b': 888 set_bell_values(optarg); 889 break; 890 case 'd': 891 print_keymap(); 892 break; 893 case 'l': 894 load_keymap(optarg, 0); 895 break; 896 case 'L': 897 load_keymap(optarg, 1); 898 break; 899 case 'f': 900 set_functionkey(optarg, 901 nextarg(argc, argv, &optind, 'f')); 902 break; 903 case 'F': 904 load_default_functionkeys(); 905 break; 906 case 'h': 907 set_history(optarg); 908 break; 909 case 'r': 910 set_keyrates(optarg); 911 break; 912 case 'x': 913 hex = 1; 914 break; 915 default: 916 usage(); 917 } 918 if ((optind != argc) || (argc == 1)) 919 usage(); 920 exit(0); 921} 922 923 924