12088Ssos/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4228976Suqs * Copyright (c) 1994-1995 S��ren Schmidt 52088Ssos * All rights reserved. 62088Ssos * 72088Ssos * Redistribution and use in source and binary forms, with or without 82088Ssos * modification, are permitted provided that the following conditions 92088Ssos * are met: 102088Ssos * 1. Redistributions of source code must retain the above copyright 115994Ssos * notice, this list of conditions and the following disclaimer, 125994Ssos * in this position and unchanged. 132088Ssos * 2. Redistributions in binary form must reproduce the above copyright 142088Ssos * notice, this list of conditions and the following disclaimer in the 152088Ssos * documentation and/or other materials provided with the distribution. 162088Ssos * 3. The name of the author may not be used to endorse or promote products 1797748Sschweikh * derived from this software without specific prior written permission 182088Ssos * 192088Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 202088Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 212088Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 222088Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 232088Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 242088Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252088Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262088Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272088Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 282088Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292088Ssos */ 302088Ssos 31114601Sobrien#include <sys/cdefs.h> 32114601Sobrien__FBSDID("$FreeBSD: stable/11/usr.sbin/kbdcontrol/kbdcontrol.c 344124 2019-02-14 15:33:04Z se $"); 3329603Scharnier 342088Ssos#include <ctype.h> 3529603Scharnier#include <err.h> 362088Ssos#include <stdio.h> 3729603Scharnier#include <stdlib.h> 383864Sswallace#include <string.h> 3929603Scharnier#include <unistd.h> 4042505Syokota#include <fcntl.h> 4166834Sphk#include <sys/kbio.h> 4266834Sphk#include <sys/consio.h> 43296926Semaste#include <sys/queue.h> 44266839Sray#include <sys/sysctl.h> 452088Ssos#include "path.h" 462088Ssos#include "lex.h" 472088Ssos 4876643Simp/* 4990394Sru * HALT, PDWN, and PASTE aren't defined in 4.x, but we need them to bridge 5090394Sru * to 5.0-current so define them here as a stop gap transition measure. 5176643Simp */ 5290394Sru#ifndef HALT 5390394Sru#define HALT 0xa1 /* halt machine */ 5490394Sru#endif 5590394Sru#ifndef PDWN 5690394Sru#define PDWN 0xa2 /* halt machine and power down */ 5790394Sru#endif 5876643Simp#ifndef PASTE 5976643Simp#define PASTE 0xa3 /* paste from cut-paste buffer */ 6076643Simp#endif 6176643Simp 62196500Sed#define SPECIAL 0x80000000 63196500Sed 64228437Sedstatic const char ctrl_names[32][4] = { 658857Srgrimes "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 662088Ssos "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 672088Ssos "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 6838139Syokota "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 692088Ssos }; 702088Ssos 71228437Sedstatic const char acc_names[15][5] = { 7232316Syokota "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 7332316Syokota "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 7432316Syokota "dcar", 7532316Syokota }; 7632316Syokota 77228437Sedstatic const char acc_names_u[15][5] = { 7832316Syokota "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 7932316Syokota "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 8032316Syokota "DCAR", 8132316Syokota }; 8232316Syokota 83228437Sedstatic const char fkey_table[96][MAXFK] = { 845994Ssos/* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 855994Ssos/* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 865994Ssos/* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 875994Ssos/* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 885994Ssos/* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 895994Ssos/* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 905994Ssos/* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 915994Ssos/* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 925994Ssos/* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 935994Ssos/* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 945994Ssos/* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 959202Srgrimes/* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 965994Ssos/* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 975994Ssos/* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 985994Ssos/* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 999202Srgrimes/* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 1005994Ssos/* 65-68 */ "" , "" , "" , "" , 1015994Ssos/* 69-72 */ "" , "" , "" , "" , 1025994Ssos/* 73-76 */ "" , "" , "" , "" , 1035994Ssos/* 77-80 */ "" , "" , "" , "" , 1045994Ssos/* 81-84 */ "" , "" , "" , "" , 1055994Ssos/* 85-88 */ "" , "" , "" , "" , 1065994Ssos/* 89-92 */ "" , "" , "" , "" , 1075994Ssos/* 93-96 */ "" , "" , "" , "" , 1082088Ssos }; 1092088Ssos 110228437Sedstatic const int delays[] = {250, 500, 750, 1000}; 111228437Sedstatic const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 112228437Sed 68, 76, 84, 92, 100, 110, 118, 126, 113228437Sed 136, 152, 168, 184, 200, 220, 236, 252, 114228437Sed 272, 304, 336, 368, 400, 440, 472, 504}; 115228437Sedstatic const int ndelays = (sizeof(delays) / sizeof(int)); 116228437Sedstatic const int nrepeats = (sizeof(repeats) / sizeof(int)); 117228437Sedstatic int hex = 0; 118296926Semastestatic int paths_configured = 0; 119228437Sedstatic int token; 1202088Ssos 121228437Sedint number; 122228437Sedchar letter; 1232088Ssos 124296926Semastestatic void add_keymap_path(const char *path); 125228437Sedstatic void dump_accent_definition(char *name, accentmap_t *accentmap); 126228437Sedstatic void dump_entry(int value); 127228437Sedstatic void dump_key_definition(char *name, keymap_t *keymap); 128228437Sedstatic int get_accent_definition_line(accentmap_t *); 129228437Sedstatic int get_entry(void); 130228437Sedstatic int get_key_definition_line(keymap_t *); 131228437Sedstatic void load_keymap(char *opt, int dumponly); 132228437Sedstatic void load_default_functionkeys(void); 133228437Sedstatic char * nextarg(int ac, char **av, int *indp, int oc); 134228437Sedstatic char * mkfullname(const char *s1, const char *s2, const char *s3); 135228437Sedstatic void print_accent_definition_line(FILE *fp, int accent, 136228437Sed struct acc_t *key); 137228437Sedstatic void print_entry(FILE *fp, int value); 138228437Sedstatic void print_key_definition_line(FILE *fp, int scancode, 139228437Sed struct keyent_t *key); 140228437Sedstatic void print_keymap(void); 141228437Sedstatic void release_keyboard(void); 142228437Sedstatic void mux_keyboard(u_int op, char *kbd); 143228437Sedstatic void set_bell_values(char *opt); 144228437Sedstatic void set_functionkey(char *keynumstr, char *string); 145228437Sedstatic void set_keyboard(char *device); 146228437Sedstatic void set_keyrates(char *opt); 147228437Sedstatic void show_kbd_info(void); 148228437Sedstatic void usage(void) __dead2; 149228437Sed 150296926Semastestruct pathent { 151296926Semaste STAILQ_ENTRY(pathent) next; 152296926Semaste char *path; 153296926Semaste}; 154296926Semastestatic STAILQ_HEAD(, pathent) pathlist = STAILQ_HEAD_INITIALIZER(pathlist); 155296926Semaste 156266839Sray/* Detect presence of vt(4). */ 157266839Sraystatic int 158266839Srayis_vt4(void) 159266839Sray{ 160268175Semaste char vty_name[4] = ""; 161268175Semaste size_t len = sizeof(vty_name); 162266839Sray 163268175Semaste if (sysctlbyname("kern.vty", vty_name, &len, NULL, 0) != 0) 164268175Semaste return (0); 165268175Semaste return (strcmp(vty_name, "vt") == 0); 166266839Sray} 167266839Sray 168228437Sedstatic char * 1692088Ssosnextarg(int ac, char **av, int *indp, int oc) 1702088Ssos{ 1712088Ssos if (*indp < ac) 1722088Ssos return(av[(*indp)++]); 17329603Scharnier warnx("option requires two arguments -- %c", oc); 1742088Ssos usage(); 1752088Ssos} 1762088Ssos 1772088Ssos 178228437Sedstatic char * 1792088Ssosmkfullname(const char *s1, const char *s2, const char *s3) 1802088Ssos{ 1815536Ssos static char *buf = NULL; 1825536Ssos static int bufl = 0; 1835536Ssos int f; 1842088Ssos 1852088Ssos f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 18677394Ssobomax if (f > bufl) { 1872088Ssos if (buf) 1882088Ssos buf = (char *)realloc(buf, f); 1892088Ssos else 1902088Ssos buf = (char *)malloc(f); 19177394Ssobomax } 1922088Ssos if (!buf) { 1932088Ssos bufl = 0; 1942088Ssos return(NULL); 1952088Ssos } 1962088Ssos 1972088Ssos bufl = f; 1982088Ssos strcpy(buf, s1); 1992088Ssos strcat(buf, s2); 2002088Ssos strcat(buf, s3); 2012088Ssos return(buf); 2022088Ssos} 2032088Ssos 2042088Ssos 205228437Sedstatic int 20699816Salfredget_entry(void) 2072088Ssos{ 20832316Syokota switch ((token = yylex())) { 2092088Ssos case TNOP: 210196500Sed return NOP | SPECIAL; 2112088Ssos case TLSH: 212196500Sed return LSH | SPECIAL; 2132088Ssos case TRSH: 214196500Sed return RSH | SPECIAL; 2152088Ssos case TCLK: 216196500Sed return CLK | SPECIAL; 2172088Ssos case TNLK: 218196500Sed return NLK | SPECIAL; 2192088Ssos case TSLK: 220196500Sed return SLK | SPECIAL; 2212088Ssos case TBTAB: 222196500Sed return BTAB | SPECIAL; 2232088Ssos case TLALT: 224196500Sed return LALT | SPECIAL; 2252088Ssos case TLCTR: 226196500Sed return LCTR | SPECIAL; 2272088Ssos case TNEXT: 228196500Sed return NEXT | SPECIAL; 22948105Syokota case TPREV: 230196500Sed return PREV | SPECIAL; 2312088Ssos case TRCTR: 232196500Sed return RCTR | SPECIAL; 2332088Ssos case TRALT: 234196500Sed return RALT | SPECIAL; 2352088Ssos case TALK: 236196500Sed return ALK | SPECIAL; 2372088Ssos case TASH: 238196500Sed return ASH | SPECIAL; 2392088Ssos case TMETA: 240196500Sed return META | SPECIAL; 2412088Ssos case TRBT: 242196500Sed return RBT | SPECIAL; 2432088Ssos case TDBG: 244196500Sed return DBG | SPECIAL; 2455994Ssos case TSUSP: 246196500Sed return SUSP | SPECIAL; 24738053Syokota case TSPSC: 248196500Sed return SPSC | SPECIAL; 24954380Syokota case TPANIC: 250196500Sed return PNC | SPECIAL; 25154380Syokota case TLSHA: 252196500Sed return LSHA | SPECIAL; 25354380Syokota case TRSHA: 254196500Sed return RSHA | SPECIAL; 25554380Syokota case TLCTRA: 256196500Sed return LCTRA | SPECIAL; 25754380Syokota case TRCTRA: 258196500Sed return RCTRA | SPECIAL; 25954380Syokota case TLALTA: 260196500Sed return LALTA | SPECIAL; 26154380Syokota case TRALTA: 262196500Sed return RALTA | SPECIAL; 26365759Sdwmalone case THALT: 264196500Sed return HALT | SPECIAL; 26565759Sdwmalone case TPDWN: 266196500Sed return PDWN | SPECIAL; 26774118Sache case TPASTE: 268196500Sed return PASTE | SPECIAL; 26932316Syokota case TACC: 27032316Syokota if (ACC(number) > L_ACC) 27132316Syokota return -1; 272196500Sed return ACC(number) | SPECIAL; 2732088Ssos case TFUNC: 2742088Ssos if (F(number) > L_FN) 2752088Ssos return -1; 276196500Sed return F(number) | SPECIAL; 2772088Ssos case TSCRN: 2782088Ssos if (S(number) > L_SCR) 2792088Ssos return -1; 280196500Sed return S(number) | SPECIAL; 2812088Ssos case TLET: 2822088Ssos return (unsigned char)letter; 2832088Ssos case TNUM: 284197330Sed if (number < 0x000000 || number > 0x10FFFF) 2852088Ssos return -1; 2862088Ssos return number; 2872088Ssos default: 2882088Ssos return -1; 2892088Ssos } 2902088Ssos} 2912088Ssos 29277394Ssobomaxstatic int 293296926Semasteget_definition_line(FILE *file, keymap_t *keymap, accentmap_t *accentmap) 2942088Ssos{ 29532316Syokota int c; 2962088Ssos 297296926Semaste yyin = file; 2982088Ssos 29932316Syokota if (token < 0) 30032316Syokota token = yylex(); 30132316Syokota switch (token) { 30232316Syokota case TNUM: 30332316Syokota c = get_key_definition_line(keymap); 30432316Syokota if (c < 0) 30532316Syokota errx(1, "invalid key definition"); 30632316Syokota if (c > keymap->n_keys) 30732316Syokota keymap->n_keys = c; 30832316Syokota break; 30932316Syokota case TACC: 31032316Syokota c = get_accent_definition_line(accentmap); 31132316Syokota if (c < 0) 31232316Syokota errx(1, "invalid accent key definition"); 31332316Syokota if (c > accentmap->n_accs) 31432316Syokota accentmap->n_accs = c; 31532316Syokota break; 31632316Syokota case 0: 31732316Syokota /* EOF */ 3182088Ssos return -1; 31932316Syokota default: 32032316Syokota errx(1, "illegal definition line"); 32132316Syokota } 32232316Syokota return c; 32332316Syokota} 32432316Syokota 325228437Sedstatic int 32632316Syokotaget_key_definition_line(keymap_t *map) 32732316Syokota{ 32832316Syokota int i, def, scancode; 32932316Syokota 33032316Syokota /* check scancode number */ 3312088Ssos if (number < 0 || number >= NUM_KEYS) 3322088Ssos return -1; 3332088Ssos scancode = number; 3342088Ssos 3352088Ssos /* get key definitions */ 3362088Ssos map->key[scancode].spcl = 0; 3372088Ssos for (i=0; i<NUM_STATES; i++) { 3382088Ssos if ((def = get_entry()) == -1) 3392088Ssos return -1; 340196500Sed if (def & SPECIAL) 3412088Ssos map->key[scancode].spcl |= (0x80 >> i); 342196500Sed map->key[scancode].map[i] = def & ~SPECIAL; 3432088Ssos } 3442088Ssos /* get lock state key def */ 34532316Syokota if ((token = yylex()) != TFLAG) 3462088Ssos return -1; 3472088Ssos map->key[scancode].flgs = number; 34832316Syokota token = yylex(); 34932316Syokota return (scancode + 1); 3502088Ssos} 3512088Ssos 352228437Sedstatic int 35332316Syokotaget_accent_definition_line(accentmap_t *map) 35432316Syokota{ 35532316Syokota int accent; 35632316Syokota int c1, c2; 35732316Syokota int i; 3582088Ssos 35932316Syokota if (ACC(number) < F_ACC || ACC(number) > L_ACC) 36032316Syokota /* number out of range */ 36132316Syokota return -1; 36232316Syokota accent = number; 36332316Syokota if (map->acc[accent].accchar != 0) { 36432316Syokota /* this entry has already been defined before! */ 36532316Syokota errx(1, "duplicated accent key definition"); 36632316Syokota } 36732316Syokota 36832316Syokota switch ((token = yylex())) { 36932316Syokota case TLET: 37032316Syokota map->acc[accent].accchar = letter; 37132316Syokota break; 37232316Syokota case TNUM: 37332316Syokota map->acc[accent].accchar = number; 37432316Syokota break; 37532316Syokota default: 37632316Syokota return -1; 37732316Syokota } 37832316Syokota 37932316Syokota for (i = 0; (token = yylex()) == '(';) { 38032316Syokota switch ((token = yylex())) { 38132316Syokota case TLET: 38232316Syokota c1 = letter; 38332316Syokota break; 38432316Syokota case TNUM: 38532316Syokota c1 = number; 38632316Syokota break; 38732316Syokota default: 38832316Syokota return -1; 38932316Syokota } 39032316Syokota switch ((token = yylex())) { 39132316Syokota case TLET: 39232316Syokota c2 = letter; 39332316Syokota break; 39432316Syokota case TNUM: 39532316Syokota c2 = number; 39632316Syokota break; 39732316Syokota default: 39832316Syokota return -1; 39932316Syokota } 40032316Syokota if ((token = yylex()) != ')') 40132316Syokota return -1; 40232316Syokota if (i >= NUM_ACCENTCHARS) { 40332316Syokota warnx("too many accented characters, ignored"); 40432316Syokota continue; 40532316Syokota } 40632316Syokota map->acc[accent].map[i][0] = c1; 40732316Syokota map->acc[accent].map[i][1] = c2; 40832316Syokota ++i; 40932316Syokota } 41032316Syokota return (accent + 1); 41132316Syokota} 41232316Syokota 413228437Sedstatic void 4142088Ssosprint_entry(FILE *fp, int value) 4152088Ssos{ 416196500Sed int val = value & ~SPECIAL; 4172088Ssos 4182088Ssos switch (value) { 419196500Sed case NOP | SPECIAL: 4208857Srgrimes fprintf(fp, " nop "); 4212088Ssos break; 422196500Sed case LSH | SPECIAL: 4232088Ssos fprintf(fp, " lshift"); 4242088Ssos break; 425196500Sed case RSH | SPECIAL: 4262088Ssos fprintf(fp, " rshift"); 4272088Ssos break; 428196500Sed case CLK | SPECIAL: 4292088Ssos fprintf(fp, " clock "); 4302088Ssos break; 431196500Sed case NLK | SPECIAL: 4322088Ssos fprintf(fp, " nlock "); 4332088Ssos break; 434196500Sed case SLK | SPECIAL: 4352088Ssos fprintf(fp, " slock "); 4362088Ssos break; 437196500Sed case BTAB | SPECIAL: 4382088Ssos fprintf(fp, " btab "); 4392088Ssos break; 440196500Sed case LALT | SPECIAL: 4412088Ssos fprintf(fp, " lalt "); 4422088Ssos break; 443196500Sed case LCTR | SPECIAL: 4442088Ssos fprintf(fp, " lctrl "); 4452088Ssos break; 446196500Sed case NEXT | SPECIAL: 4472088Ssos fprintf(fp, " nscr "); 4482088Ssos break; 449196500Sed case PREV | SPECIAL: 45048105Syokota fprintf(fp, " pscr "); 45148105Syokota break; 452196500Sed case RCTR | SPECIAL: 4532088Ssos fprintf(fp, " rctrl "); 4542088Ssos break; 455196500Sed case RALT | SPECIAL: 4562088Ssos fprintf(fp, " ralt "); 4572088Ssos break; 458196500Sed case ALK | SPECIAL: 4592088Ssos fprintf(fp, " alock "); 4602088Ssos break; 461196500Sed case ASH | SPECIAL: 4622088Ssos fprintf(fp, " ashift"); 4632088Ssos break; 464196500Sed case META | SPECIAL: 4652088Ssos fprintf(fp, " meta "); 4662088Ssos break; 467196500Sed case RBT | SPECIAL: 4682088Ssos fprintf(fp, " boot "); 4692088Ssos break; 470196500Sed case DBG | SPECIAL: 4712088Ssos fprintf(fp, " debug "); 4722088Ssos break; 473196500Sed case SUSP | SPECIAL: 47432316Syokota fprintf(fp, " susp "); 47532316Syokota break; 476196500Sed case SPSC | SPECIAL: 47738053Syokota fprintf(fp, " saver "); 47838053Syokota break; 479196500Sed case PNC | SPECIAL: 48054380Syokota fprintf(fp, " panic "); 48154380Syokota break; 482196500Sed case LSHA | SPECIAL: 48354380Syokota fprintf(fp, " lshifta"); 48454380Syokota break; 485196500Sed case RSHA | SPECIAL: 48654380Syokota fprintf(fp, " rshifta"); 48754380Syokota break; 488196500Sed case LCTRA | SPECIAL: 48954380Syokota fprintf(fp, " lctrla"); 49054380Syokota break; 491196500Sed case RCTRA | SPECIAL: 49254380Syokota fprintf(fp, " rctrla"); 49354380Syokota break; 494196500Sed case LALTA | SPECIAL: 49554380Syokota fprintf(fp, " lalta "); 49654380Syokota break; 497196500Sed case RALTA | SPECIAL: 49854380Syokota fprintf(fp, " ralta "); 49954380Syokota break; 500196500Sed case HALT | SPECIAL: 50165759Sdwmalone fprintf(fp, " halt "); 50265759Sdwmalone break; 503196500Sed case PDWN | SPECIAL: 50465759Sdwmalone fprintf(fp, " pdwn "); 50565759Sdwmalone break; 506196500Sed case PASTE | SPECIAL: 50774118Sache fprintf(fp, " paste "); 50874118Sache break; 5092088Ssos default: 510196500Sed if (value & SPECIAL) { 5118857Srgrimes if (val >= F_FN && val <= L_FN) 5122088Ssos fprintf(fp, " fkey%02d", val - F_FN + 1); 5138857Srgrimes else if (val >= F_SCR && val <= L_SCR) 5142088Ssos fprintf(fp, " scr%02d ", val - F_SCR + 1); 51532316Syokota else if (val >= F_ACC && val <= L_ACC) 51632316Syokota fprintf(fp, " %-6s", acc_names[val - F_ACC]); 5172088Ssos else if (hex) 5188857Srgrimes fprintf(fp, " 0x%02x ", val); 5192088Ssos else 52032316Syokota fprintf(fp, " %3d ", val); 5212088Ssos } 5222088Ssos else { 5232088Ssos if (val < ' ') 5248857Srgrimes fprintf(fp, " %s ", ctrl_names[val]); 5252088Ssos else if (val == 127) 5268857Srgrimes fprintf(fp, " del "); 5279202Srgrimes else if (isascii(val) && isprint(val)) 5288857Srgrimes fprintf(fp, " '%c' ", val); 5292088Ssos else if (hex) 5308857Srgrimes fprintf(fp, " 0x%02x ", val); 5312088Ssos else 5328857Srgrimes fprintf(fp, " %3d ", val); 5332088Ssos } 5342088Ssos } 5352088Ssos} 5362088Ssos 537228437Sedstatic void 53842505Syokotaprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key) 5392088Ssos{ 54029603Scharnier int i; 5412088Ssos 5422088Ssos /* print scancode number */ 5432088Ssos if (hex) 5442088Ssos fprintf(fp, " 0x%02x ", scancode); 5452088Ssos else 5462088Ssos fprintf(fp, " %03d ", scancode); 5472088Ssos 5482088Ssos /* print key definitions */ 5492088Ssos for (i=0; i<NUM_STATES; i++) { 5502088Ssos if (key->spcl & (0x80 >> i)) 551196500Sed print_entry(fp, key->map[i] | SPECIAL); 5522088Ssos else 5538857Srgrimes print_entry(fp, key->map[i]); 5542088Ssos } 5552088Ssos 5562088Ssos /* print lock state key def */ 5572088Ssos switch (key->flgs) { 5582088Ssos case 0: 5592088Ssos fprintf(fp, " O\n"); 5602088Ssos break; 5612088Ssos case 1: 5622088Ssos fprintf(fp, " C\n"); 5632088Ssos break; 5642088Ssos case 2: 5652088Ssos fprintf(fp, " N\n"); 5662088Ssos break; 5676046Ssos case 3: 5686046Ssos fprintf(fp, " B\n"); 5696046Ssos break; 5708857Srgrimes } 5712088Ssos} 5722088Ssos 573228437Sedstatic void 57432316Syokotaprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 57532316Syokota{ 57632316Syokota int c; 57732316Syokota int i; 5782088Ssos 57932316Syokota if (key->accchar == 0) 58032316Syokota return; 58132316Syokota 58232316Syokota /* print accent number */ 58332316Syokota fprintf(fp, " %-6s", acc_names[accent]); 58432316Syokota if (isascii(key->accchar) && isprint(key->accchar)) 58532316Syokota fprintf(fp, "'%c' ", key->accchar); 58632316Syokota else if (hex) 58732316Syokota fprintf(fp, "0x%02x ", key->accchar); 58832316Syokota else 58932316Syokota fprintf(fp, "%03d ", key->accchar); 59032316Syokota 59132316Syokota for (i = 0; i < NUM_ACCENTCHARS; ++i) { 59232316Syokota c = key->map[i][0]; 59332316Syokota if (c == 0) 59432316Syokota break; 59532316Syokota if ((i > 0) && ((i % 4) == 0)) 59632316Syokota fprintf(fp, "\n "); 59732316Syokota if (isascii(c) && isprint(c)) 59832316Syokota fprintf(fp, "( '%c' ", c); 59932316Syokota else if (hex) 60032316Syokota fprintf(fp, "(0x%02x ", c); 60132316Syokota else 60232316Syokota fprintf(fp, "( %03d ", c); 60332316Syokota c = key->map[i][1]; 60432316Syokota if (isascii(c) && isprint(c)) 60532316Syokota fprintf(fp, "'%c' ) ", c); 60632316Syokota else if (hex) 60732316Syokota fprintf(fp, "0x%02x) ", c); 60832316Syokota else 60932316Syokota fprintf(fp, "%03d ) ", c); 61032316Syokota } 61132316Syokota fprintf(fp, "\n"); 61232316Syokota} 61332316Syokota 614228437Sedstatic void 61532316Syokotadump_entry(int value) 61632316Syokota{ 617196500Sed if (value & SPECIAL) { 618196500Sed value &= ~SPECIAL; 61932316Syokota switch (value) { 62032316Syokota case NOP: 62132316Syokota printf(" NOP, "); 62232316Syokota break; 62332316Syokota case LSH: 62432316Syokota printf(" LSH, "); 62532316Syokota break; 62632316Syokota case RSH: 62732316Syokota printf(" RSH, "); 62832316Syokota break; 62932316Syokota case CLK: 63032316Syokota printf(" CLK, "); 63132316Syokota break; 63232316Syokota case NLK: 63332316Syokota printf(" NLK, "); 63432316Syokota break; 63532316Syokota case SLK: 63632316Syokota printf(" SLK, "); 63732316Syokota break; 63832316Syokota case BTAB: 63932316Syokota printf(" BTAB, "); 64032316Syokota break; 64132316Syokota case LALT: 64232316Syokota printf(" LALT, "); 64332316Syokota break; 64432316Syokota case LCTR: 64532316Syokota printf(" LCTR, "); 64632316Syokota break; 64732316Syokota case NEXT: 64832316Syokota printf(" NEXT, "); 64932316Syokota break; 65048105Syokota case PREV: 65148105Syokota printf(" PREV, "); 65248105Syokota break; 65332316Syokota case RCTR: 65432316Syokota printf(" RCTR, "); 65532316Syokota break; 65632316Syokota case RALT: 65732316Syokota printf(" RALT, "); 65832316Syokota break; 65932316Syokota case ALK: 66032316Syokota printf(" ALK, "); 66132316Syokota break; 66232316Syokota case ASH: 66332316Syokota printf(" ASH, "); 66432316Syokota break; 66532316Syokota case META: 66632316Syokota printf(" META, "); 66732316Syokota break; 66832316Syokota case RBT: 66932316Syokota printf(" RBT, "); 67032316Syokota break; 67132316Syokota case DBG: 67232316Syokota printf(" DBG, "); 67332316Syokota break; 67432316Syokota case SUSP: 67532316Syokota printf(" SUSP, "); 67632316Syokota break; 67738053Syokota case SPSC: 67838053Syokota printf(" SPSC, "); 67938053Syokota break; 68054380Syokota case PNC: 68154380Syokota printf(" PNC, "); 68254380Syokota break; 68354380Syokota case LSHA: 68454380Syokota printf(" LSHA, "); 68554380Syokota break; 68654380Syokota case RSHA: 68754380Syokota printf(" RSHA, "); 68854380Syokota break; 68954380Syokota case LCTRA: 69054380Syokota printf("LCTRA, "); 69154380Syokota break; 69254380Syokota case RCTRA: 69354380Syokota printf("RCTRA, "); 69454380Syokota break; 69554380Syokota case LALTA: 69654380Syokota printf("LALTA, "); 69754380Syokota break; 69854380Syokota case RALTA: 69954380Syokota printf("RALTA, "); 70054380Syokota break; 70165759Sdwmalone case HALT: 70265759Sdwmalone printf(" HALT, "); 70365759Sdwmalone break; 70465759Sdwmalone case PDWN: 70565759Sdwmalone printf(" PDWN, "); 70665759Sdwmalone break; 70774118Sache case PASTE: 70874118Sache printf("PASTE, "); 70974118Sache break; 71032316Syokota default: 71132316Syokota if (value >= F_FN && value <= L_FN) 71232316Syokota printf(" F(%2d),", value - F_FN + 1); 71332316Syokota else if (value >= F_SCR && value <= L_SCR) 71432486Syokota printf(" S(%2d),", value - F_SCR + 1); 71532316Syokota else if (value >= F_ACC && value <= L_ACC) 71632316Syokota printf(" %-4s, ", acc_names_u[value - F_ACC]); 71732316Syokota else 71832316Syokota printf(" 0x%02X, ", value); 71932316Syokota break; 72032316Syokota } 72132316Syokota } else if (value == '\'') { 72232316Syokota printf(" '\\'', "); 72332316Syokota } else if (value == '\\') { 72432316Syokota printf(" '\\\\', "); 72532316Syokota } else if (isascii(value) && isprint(value)) { 72632316Syokota printf(" '%c', ", value); 72732316Syokota } else { 72832316Syokota printf(" 0x%02X, ", value); 72932316Syokota } 73032316Syokota} 73132316Syokota 732228437Sedstatic void 73332316Syokotadump_key_definition(char *name, keymap_t *keymap) 73432316Syokota{ 73532316Syokota int i, j; 73632316Syokota 73732486Syokota printf("static keymap_t keymap_%s = { 0x%02x, {\n", 73832316Syokota name, (unsigned)keymap->n_keys); 73932316Syokota printf( 74032486Syokota"/* alt\n" 74132486Syokota" * scan cntrl alt alt cntrl\n" 74232486Syokota" * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 74332316Syokota" * ---------------------------------------------------------------------------\n" 74432316Syokota" */\n"); 74532316Syokota for (i = 0; i < keymap->n_keys; i++) { 74632486Syokota printf("/*%02x*/{{", i); 74732316Syokota for (j = 0; j < NUM_STATES; j++) { 74832316Syokota if (keymap->key[i].spcl & (0x80 >> j)) 749196500Sed dump_entry(keymap->key[i].map[j] | SPECIAL); 75032316Syokota else 75132316Syokota dump_entry(keymap->key[i].map[j]); 75232316Syokota } 75332486Syokota printf("}, 0x%02X,0x%02X },\n", 75432316Syokota (unsigned)keymap->key[i].spcl, 75532316Syokota (unsigned)keymap->key[i].flgs); 75632316Syokota } 75732486Syokota printf("} };\n\n"); 75832316Syokota} 75932316Syokota 760228437Sedstatic void 76132316Syokotadump_accent_definition(char *name, accentmap_t *accentmap) 76232316Syokota{ 76332316Syokota int i, j; 76432316Syokota int c; 76532316Syokota 76632486Syokota printf("static accentmap_t accentmap_%s = { %d", 76732316Syokota name, accentmap->n_accs); 76832486Syokota if (accentmap->n_accs <= 0) { 76932486Syokota printf(" };\n\n"); 77032486Syokota return; 77132486Syokota } 77232486Syokota printf(", {\n"); 77332316Syokota for (i = 0; i < NUM_DEADKEYS; i++) { 77432316Syokota printf(" /* %s=%d */\n {", acc_names[i], i); 77532316Syokota c = accentmap->acc[i].accchar; 77632316Syokota if (c == '\'') 77732316Syokota printf(" '\\'', {"); 77832316Syokota else if (c == '\\') 77932316Syokota printf(" '\\\\', {"); 78032316Syokota else if (isascii(c) && isprint(c)) 78132316Syokota printf(" '%c', {", c); 78232316Syokota else if (c == 0) { 78332316Syokota printf(" 0x00 }, \n"); 78432316Syokota continue; 78532316Syokota } else 78632316Syokota printf(" 0x%02x, {", c); 78732316Syokota for (j = 0; j < NUM_ACCENTCHARS; j++) { 78832316Syokota c = accentmap->acc[i].map[j][0]; 78932316Syokota if (c == 0) 79032316Syokota break; 79132316Syokota if ((j > 0) && ((j % 4) == 0)) 79232316Syokota printf("\n\t "); 79332316Syokota if (isascii(c) && isprint(c)) 79432316Syokota printf(" { '%c',", c); 79532316Syokota else 79632316Syokota printf(" { 0x%02x,", c); 79732316Syokota printf("0x%02x },", accentmap->acc[i].map[j][1]); 79832316Syokota } 79932316Syokota printf(" }, },\n"); 80032316Syokota } 80132486Syokota printf("} };\n\n"); 80232316Syokota} 80332316Syokota 804228437Sedstatic void 805296926Semasteadd_keymap_path(const char *path) 806296926Semaste{ 807296926Semaste struct pathent* pe; 808296926Semaste size_t len; 809296926Semaste 810296926Semaste len = strlen(path); 811296926Semaste if ((pe = malloc(sizeof(*pe))) == NULL || 812296926Semaste (pe->path = malloc(len + 2)) == NULL) 813296926Semaste err(1, "malloc"); 814296926Semaste memcpy(pe->path, path, len); 815296926Semaste if (len > 0 && path[len - 1] != '/') 816296926Semaste pe->path[len++] = '/'; 817296926Semaste pe->path[len] = '\0'; 818296926Semaste STAILQ_INSERT_TAIL(&pathlist, pe, next); 819296926Semaste} 820296926Semaste 821296926Semastestatic void 82219569Sjoergload_keymap(char *opt, int dumponly) 8232088Ssos{ 82432316Syokota keymap_t keymap; 82532316Syokota accentmap_t accentmap; 826296926Semaste struct pathent *pe; 827296926Semaste FILE *file; 828296926Semaste int j; 82919569Sjoerg char *name, *cp; 830266839Sray char blank[] = "", keymap_path[] = KEYMAP_PATH; 831266839Sray char vt_keymap_path[] = VT_KEYMAP_PATH, dotkbd[] = ".kbd"; 83299816Salfred char *postfix[] = {blank, dotkbd, NULL}; 8332088Ssos 834296926Semaste if (!paths_configured) { 835296926Semaste cp = getenv("KEYMAP_PATH"); 836296926Semaste if (cp != NULL) 837296926Semaste add_keymap_path(cp); 838296926Semaste add_keymap_path(""); 839296926Semaste if (is_vt4()) 840296926Semaste add_keymap_path(vt_keymap_path); 841296926Semaste else 842296926Semaste add_keymap_path(keymap_path); 843296926Semaste paths_configured = 1; 844296926Semaste } 84576502Ssobomax 846296926Semaste file = NULL; 847296926Semaste STAILQ_FOREACH(pe, &pathlist, next) { 848296926Semaste for (j=0; postfix[j] && file == NULL; j++) { 849296926Semaste name = mkfullname(pe->path, opt, postfix[j]); 850296926Semaste file = fopen(name, "r"); 851296926Semaste if (file != NULL) 852296926Semaste break; 85376502Ssobomax } 85476643Simp } 855296926Semaste if (file == NULL) { 85679677Sobrien warn("keymap file \"%s\" not found", opt); 8572088Ssos return; 8582088Ssos } 85932316Syokota memset(&keymap, 0, sizeof(keymap)); 86032316Syokota memset(&accentmap, 0, sizeof(accentmap)); 86132316Syokota token = -1; 8622088Ssos while (1) { 863296926Semaste if (get_definition_line(file, &keymap, &accentmap) < 0) 8642088Ssos break; 8652088Ssos } 86619569Sjoerg if (dumponly) { 86719569Sjoerg /* fix up the filename to make it a valid C identifier */ 86819569Sjoerg for (cp = opt; *cp; cp++) 86919569Sjoerg if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 87032316Syokota printf("/*\n" 87132316Syokota " * Automatically generated from %s.\n" 87232316Syokota " * DO NOT EDIT!\n" 87332316Syokota " */\n", name); 87432316Syokota dump_key_definition(opt, &keymap); 87532316Syokota dump_accent_definition(opt, &accentmap); 87619569Sjoerg return; 87719569Sjoerg } 87832316Syokota if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 87929603Scharnier warn("setting keymap"); 880296926Semaste fclose(file); 8812088Ssos return; 8822088Ssos } 88332316Syokota if ((accentmap.n_accs > 0) 88432316Syokota && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 88532316Syokota warn("setting accentmap"); 886296926Semaste fclose(file); 88732316Syokota return; 88832316Syokota } 8892088Ssos} 8902088Ssos 891228437Sedstatic void 89299816Salfredprint_keymap(void) 8932088Ssos{ 89432316Syokota keymap_t keymap; 89532316Syokota accentmap_t accentmap; 8962088Ssos int i; 8972088Ssos 89832316Syokota if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 89929603Scharnier err(1, "getting keymap"); 90032316Syokota if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 90132316Syokota memset(&accentmap, 0, sizeof(accentmap)); 9022088Ssos printf( 9032088Ssos"# alt\n" 9042088Ssos"# scan cntrl alt alt cntrl lock\n" 9052088Ssos"# code base shift cntrl shift alt shift cntrl shift state\n" 9062088Ssos"# ------------------------------------------------------------------\n" 9072088Ssos ); 90832316Syokota for (i=0; i<keymap.n_keys; i++) 90932316Syokota print_key_definition_line(stdout, i, &keymap.key[i]); 91032316Syokota 91132316Syokota printf("\n"); 91232316Syokota for (i = 0; i < NUM_DEADKEYS; i++) 91332316Syokota print_accent_definition_line(stdout, i, &accentmap.acc[i]); 91432316Syokota 9152088Ssos} 9162088Ssos 917228437Sedstatic void 91899816Salfredload_default_functionkeys(void) 9192088Ssos{ 9202088Ssos fkeyarg_t fkey; 9212088Ssos int i; 9222088Ssos 9232088Ssos for (i=0; i<NUM_FKEYS; i++) { 9242088Ssos fkey.keynum = i; 9252088Ssos strcpy(fkey.keydef, fkey_table[i]); 9262088Ssos fkey.flen = strlen(fkey_table[i]); 9272088Ssos if (ioctl(0, SETFKEY, &fkey) < 0) 92829603Scharnier warn("setting function key"); 9292088Ssos } 9302088Ssos} 9312088Ssos 932228437Sedstatic void 9332088Ssosset_functionkey(char *keynumstr, char *string) 9342088Ssos{ 9352088Ssos fkeyarg_t fkey; 9362088Ssos 9372088Ssos if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 9382088Ssos load_default_functionkeys(); 9392088Ssos return; 9402088Ssos } 9412088Ssos fkey.keynum = atoi(keynumstr); 9422088Ssos if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 94329603Scharnier warnx("function key number must be between 1 and %d", 9442088Ssos NUM_FKEYS); 9452088Ssos return; 9462088Ssos } 9472088Ssos if ((fkey.flen = strlen(string)) > MAXFK) { 94829603Scharnier warnx("function key string too long (%d > %d)", 9492088Ssos fkey.flen, MAXFK); 9502088Ssos return; 9512088Ssos } 952133353Sjmg strncpy(fkey.keydef, string, MAXFK); 9532088Ssos fkey.keynum -= 1; 9542088Ssos if (ioctl(0, SETFKEY, &fkey) < 0) 95529603Scharnier warn("setting function key"); 9562088Ssos} 9572088Ssos 958228437Sedstatic void 9592088Ssosset_bell_values(char *opt) 9602088Ssos{ 9615536Ssos int bell, duration, pitch; 9622088Ssos 96338044Syokota bell = 0; 964344124Sse duration = 0; 965344124Sse pitch = 0; 96638044Syokota if (!strncmp(opt, "quiet.", 6)) { 967164333Sru bell = CONS_QUIET_BELL; 96838044Syokota opt += 6; 96938044Syokota } 9708857Srgrimes if (!strcmp(opt, "visual")) 971164333Sru bell |= CONS_VISUAL_BELL; 9725536Ssos else if (!strcmp(opt, "normal")) 97338044Syokota duration = 5, pitch = 800; 97448982Syokota else if (!strcmp(opt, "off")) 97548982Syokota duration = 0, pitch = 0; 9762088Ssos else { 9772088Ssos char *v1; 9788857Srgrimes 9795536Ssos bell = 0; 9802088Ssos duration = strtol(opt, &v1, 0); 9812088Ssos if ((duration < 0) || (*v1 != '.')) 9822088Ssos goto badopt; 9832088Ssos opt = ++v1; 9842088Ssos pitch = strtol(opt, &v1, 0); 9852088Ssos if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 9862088Ssosbadopt: 98777394Ssobomax warnx("argument to -b must be duration.pitch or [quiet.]visual|normal|off"); 9882088Ssos return; 9892088Ssos } 99038044Syokota if (pitch != 0) 99138044Syokota pitch = 1193182 / pitch; /* in Hz */ 99238044Syokota duration /= 10; /* in 10 m sec */ 9932088Ssos } 9942088Ssos 9955536Ssos ioctl(0, CONS_BELLTYPE, &bell); 996344124Sse if (duration > 0 && pitch > 0) 997344124Sse fprintf(stderr, "\e[=%d;%dB", pitch, duration); 9982088Ssos} 9992088Ssos 1000228437Sedstatic void 10012088Ssosset_keyrates(char *opt) 10022088Ssos{ 100344628Syokota int arg[2]; 100439047Syokota int repeat; 100539047Syokota int delay; 100646761Syokota int r, d; 10072088Ssos 100846761Syokota if (!strcmp(opt, "slow")) { 100944628Syokota delay = 1000, repeat = 500; 101046761Syokota d = 3, r = 31; 101146761Syokota } else if (!strcmp(opt, "normal")) { 101244628Syokota delay = 500, repeat = 125; 101346761Syokota d = 1, r = 15; 101446761Syokota } else if (!strcmp(opt, "fast")) { 101539047Syokota delay = repeat = 0; 101646761Syokota d = r = 0; 101746761Syokota } else { 10182088Ssos int n; 10192088Ssos char *v1; 10202088Ssos 10212088Ssos delay = strtol(opt, &v1, 0); 10222088Ssos if ((delay < 0) || (*v1 != '.')) 10232088Ssos goto badopt; 10242088Ssos opt = ++v1; 10252088Ssos repeat = strtol(opt, &v1, 0); 10262088Ssos if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 10272088Ssosbadopt: 102877394Ssobomax warnx("argument to -r must be delay.repeat or slow|normal|fast"); 10292088Ssos return; 10302088Ssos } 103146761Syokota for (n = 0; n < ndelays - 1; n++) 103246761Syokota if (delay <= delays[n]) 103346761Syokota break; 103446761Syokota d = n; 103546761Syokota for (n = 0; n < nrepeats - 1; n++) 103646761Syokota if (repeat <= repeats[n]) 103746761Syokota break; 103846761Syokota r = n; 10392088Ssos } 10402088Ssos 104144628Syokota arg[0] = delay; 104244628Syokota arg[1] = repeat; 104346761Syokota if (ioctl(0, KDSETREPEAT, arg)) { 104446761Syokota if (ioctl(0, KDSETRAD, (d << 5) | r)) 104546761Syokota warn("setting keyboard rate"); 104646761Syokota } 10472088Ssos} 10482088Ssos 104999816Salfredstatic const char * 105099816Salfredget_kbd_type_name(int type) 105142505Syokota{ 105242505Syokota static struct { 105342505Syokota int type; 105499816Salfred const char *name; 105542505Syokota } name_table[] = { 105642505Syokota { KB_84, "AT 84" }, 105742505Syokota { KB_101, "AT 101/102" }, 105842505Syokota { KB_OTHER, "generic" }, 105942505Syokota }; 106099816Salfred unsigned int i; 10616046Ssos 106242505Syokota for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 106342505Syokota if (type == name_table[i].type) 106442505Syokota return name_table[i].name; 106542505Syokota } 106642505Syokota return "unknown"; 106742505Syokota} 106842505Syokota 1069228437Sedstatic void 107042505Syokotashow_kbd_info(void) 107142505Syokota{ 107242505Syokota keyboard_info_t info; 107342505Syokota 107442505Syokota if (ioctl(0, KDGKBINFO, &info) == -1) { 107542505Syokota warn("unable to obtain keyboard information"); 107642505Syokota return; 107742505Syokota } 107842505Syokota printf("kbd%d:\n", info.kb_index); 107942505Syokota printf(" %.*s%d, type:%s (%d)\n", 108077394Ssobomax (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 108142505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 108242505Syokota} 108342505Syokota 1084228437Sedstatic void 108542505Syokotaset_keyboard(char *device) 108642505Syokota{ 108742505Syokota keyboard_info_t info; 108842505Syokota int fd; 108942505Syokota 109042505Syokota fd = open(device, O_RDONLY); 109142505Syokota if (fd < 0) { 109242505Syokota warn("cannot open %s", device); 109342505Syokota return; 109442505Syokota } 109542505Syokota if (ioctl(fd, KDGKBINFO, &info) == -1) { 109642505Syokota warn("unable to obtain keyboard information"); 109742505Syokota close(fd); 109842505Syokota return; 109942505Syokota } 110042505Syokota /* 110142505Syokota * The keyboard device driver won't release the keyboard by 110242505Syokota * the following ioctl, but it automatically will, when the device 110342505Syokota * is closed. So, we don't check error here. 110442505Syokota */ 110542505Syokota ioctl(fd, CONS_RELKBD, 0); 110642505Syokota close(fd); 110742505Syokota#if 1 110842505Syokota printf("kbd%d\n", info.kb_index); 110942505Syokota printf(" %.*s%d, type:%s (%d)\n", 111077394Ssobomax (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 111142505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 111242505Syokota#endif 111342505Syokota 111442505Syokota if (ioctl(0, CONS_SETKBD, info.kb_index) == -1) 111542505Syokota warn("unable to set keyboard"); 111642505Syokota} 111742505Syokota 1118228437Sedstatic void 111942505Syokotarelease_keyboard(void) 112042505Syokota{ 112142505Syokota keyboard_info_t info; 112242505Syokota 112342505Syokota /* 112442505Syokota * If stdin is not associated with a keyboard, the following ioctl 112542505Syokota * will fail. 112642505Syokota */ 112742505Syokota if (ioctl(0, KDGKBINFO, &info) == -1) { 112842505Syokota warn("unable to obtain keyboard information"); 112942505Syokota return; 113042505Syokota } 113142505Syokota#if 1 113242505Syokota printf("kbd%d\n", info.kb_index); 113342505Syokota printf(" %.*s%d, type:%s (%d)\n", 113477394Ssobomax (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 113542505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 113642505Syokota#endif 113742505Syokota if (ioctl(0, CONS_RELKBD, 0) == -1) 113842505Syokota warn("unable to release the keyboard"); 113942505Syokota} 114042505Syokota 1141228437Sedstatic void 1142162327Semaxmux_keyboard(u_int op, char *kbd) 1143148017Semax{ 1144148017Semax keyboard_info_t info; 1145148017Semax char *unit, *ep; 114642505Syokota 1147148017Semax /* 1148148017Semax * If stdin is not associated with a keyboard, the following ioctl 1149148017Semax * will fail. 1150148017Semax */ 1151148017Semax if (ioctl(0, KDGKBINFO, &info) == -1) { 1152148017Semax warn("unable to obtain keyboard information"); 1153148017Semax return; 1154148017Semax } 1155148017Semax#if 1 1156148017Semax printf("kbd%d\n", info.kb_index); 1157148017Semax printf(" %.*s%d, type:%s (%d)\n", 1158148017Semax (int)sizeof(info.kb_name), info.kb_name, info.kb_unit, 1159148017Semax get_kbd_type_name(info.kb_type), info.kb_type); 1160148017Semax#endif 1161148017Semax /* 1162148017Semax * split kbd into name and unit. find the right most part of the 1163148017Semax * kbd string that consist of only digits. 1164148017Semax */ 1165148017Semax 1166148017Semax memset(&info, 0, sizeof(info)); 1167148017Semax 1168148017Semax info.kb_unit = -1; 1169148017Semax ep = kbd - 1; 1170148017Semax 1171148017Semax do { 1172148017Semax unit = strpbrk(ep + 1, "0123456789"); 1173148017Semax if (unit != NULL) { 1174148017Semax info.kb_unit = strtol(unit, &ep, 10); 1175148017Semax if (*ep != '\0') 1176148017Semax info.kb_unit = -1; 1177148017Semax } 1178148017Semax } while (unit != NULL && info.kb_unit == -1); 1179148017Semax 1180148017Semax if (info.kb_unit == -1) { 1181148017Semax warnx("unable to find keyboard driver unit in '%s'", kbd); 1182148017Semax return; 1183148017Semax } 1184148017Semax 1185148017Semax if (unit == kbd) { 1186148017Semax warnx("unable to find keyboard driver name in '%s'", kbd); 1187148017Semax return; 1188148017Semax } 1189148017Semax if (unit - kbd >= (int) sizeof(info.kb_name)) { 1190148017Semax warnx("keyboard name '%s' is too long", kbd); 1191148017Semax return; 1192148017Semax } 1193148017Semax 1194148017Semax strncpy(info.kb_name, kbd, unit - kbd); 1195148017Semax 1196148017Semax /* 1197148017Semax * If stdin is not associated with a kbdmux(4) keyboard, the following 1198148017Semax * ioctl will fail. 1199148017Semax */ 1200148017Semax 1201148017Semax if (ioctl(0, op, &info) == -1) 1202148017Semax warn("unable to (un)mux the keyboard"); 1203148017Semax} 1204148017Semax 1205228437Sedstatic void 1206201387Sedusage(void) 12072088Ssos{ 120829603Scharnier fprintf(stderr, "%s\n%s\n%s\n", 1209148017Semax"usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]", 121029603Scharnier" [-r delay.repeat | speed] [-l mapfile] [-f # string]", 1211296926Semaste" [-k device] [-L mapfile] [-P path]"); 121229603Scharnier exit(1); 12132088Ssos} 12142088Ssos 12152088Ssos 121651287Speterint 12172088Ssosmain(int argc, char **argv) 12182088Ssos{ 1219296926Semaste const char *optstring = "A:a:b:df:iKk:Fl:L:P:r:x"; 12202088Ssos int opt; 12212088Ssos 1222296926Semaste /* Collect any -P arguments, regardless of where they appear. */ 1223296926Semaste while ((opt = getopt(argc, argv, optstring)) != -1) 1224296926Semaste if (opt == 'P') 1225296926Semaste add_keymap_path(optarg); 1226296926Semaste 1227296926Semaste optind = optreset = 1; 1228296926Semaste while ((opt = getopt(argc, argv, optstring)) != -1) 12292088Ssos switch(opt) { 1230148017Semax case 'A': 1231148017Semax case 'a': 1232148017Semax mux_keyboard((opt == 'A')? KBRELKBD : KBADDKBD, optarg); 1233148017Semax break; 123477329Sdes case 'b': 123577329Sdes set_bell_values(optarg); 123677329Sdes break; 123777329Sdes case 'd': 123877329Sdes print_keymap(); 123977329Sdes break; 124077329Sdes case 'l': 124177329Sdes load_keymap(optarg, 0); 124277329Sdes break; 124377329Sdes case 'L': 124477329Sdes load_keymap(optarg, 1); 124577329Sdes break; 1246296926Semaste case 'P': 1247296926Semaste break; 124877329Sdes case 'f': 124977329Sdes set_functionkey(optarg, 125077329Sdes nextarg(argc, argv, &optind, 'f')); 125177329Sdes break; 125277329Sdes case 'F': 125377329Sdes load_default_functionkeys(); 125477329Sdes break; 125577329Sdes case 'i': 125677329Sdes show_kbd_info(); 125777329Sdes break; 125877329Sdes case 'K': 125977329Sdes release_keyboard(); 126077329Sdes break; 126177329Sdes case 'k': 126277329Sdes set_keyboard(optarg); 126377329Sdes break; 126477329Sdes case 'r': 126577329Sdes set_keyrates(optarg); 126677329Sdes break; 126777329Sdes case 'x': 126877329Sdes hex = 1; 126977329Sdes break; 127077329Sdes default: 127177329Sdes usage(); 12722088Ssos } 127329603Scharnier if ((optind != argc) || (argc == 1)) 12742088Ssos usage(); 12752088Ssos exit(0); 12762088Ssos} 1277