kbdcontrol.c revision 76643
12088Ssos/*- 25536Ssos * Copyright (c) 1994-1995 S�ren Schmidt 32088Ssos * All rights reserved. 42088Ssos * 52088Ssos * Redistribution and use in source and binary forms, with or without 62088Ssos * modification, are permitted provided that the following conditions 72088Ssos * are met: 82088Ssos * 1. Redistributions of source code must retain the above copyright 95994Ssos * notice, this list of conditions and the following disclaimer, 105994Ssos * in this position and unchanged. 112088Ssos * 2. Redistributions in binary form must reproduce the above copyright 122088Ssos * notice, this list of conditions and the following disclaimer in the 132088Ssos * documentation and/or other materials provided with the distribution. 142088Ssos * 3. The name of the author may not be used to endorse or promote products 152088Ssos * derived from this software withough specific prior written permission 162088Ssos * 172088Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 182088Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 192088Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 202088Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 212088Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 222088Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232088Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242088Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252088Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 262088Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272088Ssos */ 282088Ssos 2929603Scharnier#ifndef lint 3029603Scharnierstatic const char rcsid[] = 3150479Speter "$FreeBSD: head/usr.sbin/kbdcontrol/kbdcontrol.c 76643 2001-05-15 22:53:05Z imp $"; 3229603Scharnier#endif /* not lint */ 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> 432088Ssos#include "path.h" 442088Ssos#include "lex.h" 452088Ssos 4676643Simp/* 4776643Simp * PASTE isn't defined in 4.x, but we need it to bridge to 5.0-current 4876643Simp * so define it here as a stop gap transition measure. 4976643Simp */ 5076643Simp#ifndef PASTE 5176643Simp#define PASTE 0xa3 /* paste from cut-paste buffer */ 5276643Simp#endif 5376643Simp 542088Ssoschar ctrl_names[32][4] = { 558857Srgrimes "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 562088Ssos "bs ", "ht ", "nl ", "vt ", "ff ", "cr ", "so ", "si ", 572088Ssos "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 5838139Syokota "can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us " 592088Ssos }; 602088Ssos 6132316Syokotachar acc_names[15][5] = { 6232316Syokota "dgra", "dacu", "dcir", "dtil", "dmac", "dbre", "ddot", 6332316Syokota "duml", "dsla", "drin", "dced", "dapo", "ddac", "dogo", 6432316Syokota "dcar", 6532316Syokota }; 6632316Syokota 6732316Syokotachar acc_names_u[15][5] = { 6832316Syokota "DGRA", "DACU", "DCIR", "DTIL", "DMAC", "DBRE", "DDOT", 6932316Syokota "DUML", "DSLA", "DRIN", "DCED", "DAPO", "DDAC", "DOGO", 7032316Syokota "DCAR", 7132316Syokota }; 7232316Syokota 735994Ssoschar fkey_table[96][MAXFK] = { 745994Ssos/* 01-04 */ "\033[M", "\033[N", "\033[O", "\033[P", 755994Ssos/* 05-08 */ "\033[Q", "\033[R", "\033[S", "\033[T", 765994Ssos/* 09-12 */ "\033[U", "\033[V", "\033[W", "\033[X", 775994Ssos/* 13-16 */ "\033[Y", "\033[Z", "\033[a", "\033[b", 785994Ssos/* 17-20 */ "\033[c", "\033[d", "\033[e", "\033[f", 795994Ssos/* 21-24 */ "\033[g", "\033[h", "\033[i", "\033[j", 805994Ssos/* 25-28 */ "\033[k", "\033[l", "\033[m", "\033[n", 815994Ssos/* 29-32 */ "\033[o", "\033[p", "\033[q", "\033[r", 825994Ssos/* 33-36 */ "\033[s", "\033[t", "\033[u", "\033[v", 835994Ssos/* 37-40 */ "\033[w", "\033[x", "\033[y", "\033[z", 845994Ssos/* 41-44 */ "\033[@", "\033[[", "\033[\\","\033[]", 859202Srgrimes/* 45-48 */ "\033[^", "\033[_", "\033[`", "\033[{", 865994Ssos/* 49-52 */ "\033[H", "\033[A", "\033[I", "-" , 875994Ssos/* 53-56 */ "\033[D", "\033[E", "\033[C", "+" , 885994Ssos/* 57-60 */ "\033[F", "\033[B", "\033[G", "\033[L", 899202Srgrimes/* 61-64 */ "\177", "\033[J", "\033[~", "\033[}", 905994Ssos/* 65-68 */ "" , "" , "" , "" , 915994Ssos/* 69-72 */ "" , "" , "" , "" , 925994Ssos/* 73-76 */ "" , "" , "" , "" , 935994Ssos/* 77-80 */ "" , "" , "" , "" , 945994Ssos/* 81-84 */ "" , "" , "" , "" , 955994Ssos/* 85-88 */ "" , "" , "" , "" , 965994Ssos/* 89-92 */ "" , "" , "" , "" , 975994Ssos/* 93-96 */ "" , "" , "" , "" , 982088Ssos }; 992088Ssos 10046761Syokotaconst int delays[] = {250, 500, 750, 1000}; 10146761Syokotaconst int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63, 10246761Syokota 68, 76, 84, 92, 100, 110, 118, 126, 10346761Syokota 136, 152, 168, 184, 200, 220, 236, 252, 10446761Syokota 272, 304, 336, 368, 400, 440, 472, 504}; 10546761Syokotaconst int ndelays = (sizeof(delays) / sizeof(int)); 10646761Syokotaconst int nrepeats = (sizeof(repeats) / sizeof(int)); 1072088Ssosint hex = 0; 1086046Ssosint number; 1092088Ssoschar letter; 11032316Syokotaint token; 1112088Ssos 11229603Scharnierstatic void usage __P((void)); 1132088Ssos 1142088Ssoschar * 1152088Ssosnextarg(int ac, char **av, int *indp, int oc) 1162088Ssos{ 1172088Ssos if (*indp < ac) 1182088Ssos return(av[(*indp)++]); 11929603Scharnier warnx("option requires two arguments -- %c", oc); 1202088Ssos usage(); 1212088Ssos return(""); 1222088Ssos} 1232088Ssos 1242088Ssos 1252088Ssoschar * 1262088Ssosmkfullname(const char *s1, const char *s2, const char *s3) 1272088Ssos{ 1285536Ssos static char *buf = NULL; 1295536Ssos static int bufl = 0; 1305536Ssos int f; 1312088Ssos 1322088Ssos f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 1332088Ssos if (f > bufl) 1342088Ssos if (buf) 1352088Ssos buf = (char *)realloc(buf, f); 1362088Ssos else 1372088Ssos buf = (char *)malloc(f); 1382088Ssos if (!buf) { 1392088Ssos bufl = 0; 1402088Ssos return(NULL); 1412088Ssos } 1422088Ssos 1432088Ssos bufl = f; 1442088Ssos strcpy(buf, s1); 1452088Ssos strcat(buf, s2); 1462088Ssos strcat(buf, s3); 1472088Ssos return(buf); 1482088Ssos} 1492088Ssos 1502088Ssos 1512088Ssosint 1522088Ssosget_entry() 1532088Ssos{ 15432316Syokota switch ((token = yylex())) { 1552088Ssos case TNOP: 1562088Ssos return NOP | 0x100; 1572088Ssos case TLSH: 1582088Ssos return LSH | 0x100; 1592088Ssos case TRSH: 1602088Ssos return RSH | 0x100; 1612088Ssos case TCLK: 1622088Ssos return CLK | 0x100; 1632088Ssos case TNLK: 1642088Ssos return NLK | 0x100; 1652088Ssos case TSLK: 1662088Ssos return SLK | 0x100; 1672088Ssos case TBTAB: 1682088Ssos return BTAB | 0x100; 1692088Ssos case TLALT: 1702088Ssos return LALT | 0x100; 1712088Ssos case TLCTR: 1722088Ssos return LCTR | 0x100; 1732088Ssos case TNEXT: 1742088Ssos return NEXT | 0x100; 17548105Syokota case TPREV: 17648105Syokota return PREV | 0x100; 1772088Ssos case TRCTR: 1782088Ssos return RCTR | 0x100; 1792088Ssos case TRALT: 1802088Ssos return RALT | 0x100; 1812088Ssos case TALK: 1822088Ssos return ALK | 0x100; 1832088Ssos case TASH: 1842088Ssos return ASH | 0x100; 1852088Ssos case TMETA: 1862088Ssos return META | 0x100; 1872088Ssos case TRBT: 1882088Ssos return RBT | 0x100; 1892088Ssos case TDBG: 1902088Ssos return DBG | 0x100; 1915994Ssos case TSUSP: 1925994Ssos return SUSP | 0x100; 19338053Syokota case TSPSC: 19438053Syokota return SPSC | 0x100; 19554380Syokota case TPANIC: 19654380Syokota return PNC | 0x100; 19754380Syokota case TLSHA: 19854380Syokota return LSHA | 0x100; 19954380Syokota case TRSHA: 20054380Syokota return RSHA | 0x100; 20154380Syokota case TLCTRA: 20254380Syokota return LCTRA | 0x100; 20354380Syokota case TRCTRA: 20454380Syokota return RCTRA | 0x100; 20554380Syokota case TLALTA: 20654380Syokota return LALTA | 0x100; 20754380Syokota case TRALTA: 20854380Syokota return RALTA | 0x100; 20965759Sdwmalone case THALT: 21065759Sdwmalone return HALT | 0x100; 21165759Sdwmalone case TPDWN: 21265759Sdwmalone return PDWN | 0x100; 21374118Sache case TPASTE: 21474118Sache return PASTE | 0x100; 21532316Syokota case TACC: 21632316Syokota if (ACC(number) > L_ACC) 21732316Syokota return -1; 21832316Syokota return ACC(number) | 0x100; 2192088Ssos case TFUNC: 2202088Ssos if (F(number) > L_FN) 2212088Ssos return -1; 2222088Ssos return F(number) | 0x100; 2232088Ssos case TSCRN: 2242088Ssos if (S(number) > L_SCR) 2252088Ssos return -1; 2262088Ssos return S(number) | 0x100; 2272088Ssos case TLET: 2282088Ssos return (unsigned char)letter; 2292088Ssos case TNUM: 2302088Ssos if (number < 0 || number > 255) 2312088Ssos return -1; 2322088Ssos return number; 2332088Ssos default: 2342088Ssos return -1; 2352088Ssos } 2362088Ssos} 2372088Ssos 2382088Ssosint 23932316Syokotaget_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap) 2402088Ssos{ 24132316Syokota int c; 2422088Ssos 2432088Ssos yyin = fd; 2442088Ssos 24532316Syokota if (token < 0) 24632316Syokota token = yylex(); 24732316Syokota switch (token) { 24832316Syokota case TNUM: 24932316Syokota c = get_key_definition_line(keymap); 25032316Syokota if (c < 0) 25132316Syokota errx(1, "invalid key definition"); 25232316Syokota if (c > keymap->n_keys) 25332316Syokota keymap->n_keys = c; 25432316Syokota break; 25532316Syokota case TACC: 25632316Syokota c = get_accent_definition_line(accentmap); 25732316Syokota if (c < 0) 25832316Syokota errx(1, "invalid accent key definition"); 25932316Syokota if (c > accentmap->n_accs) 26032316Syokota accentmap->n_accs = c; 26132316Syokota break; 26232316Syokota case 0: 26332316Syokota /* EOF */ 2642088Ssos return -1; 26532316Syokota default: 26632316Syokota errx(1, "illegal definition line"); 26732316Syokota } 26832316Syokota return c; 26932316Syokota} 27032316Syokota 27132316Syokotaint 27232316Syokotaget_key_definition_line(keymap_t *map) 27332316Syokota{ 27432316Syokota int i, def, scancode; 27532316Syokota 27632316Syokota /* check scancode number */ 2772088Ssos if (number < 0 || number >= NUM_KEYS) 2782088Ssos return -1; 2792088Ssos scancode = number; 2802088Ssos 2812088Ssos /* get key definitions */ 2822088Ssos map->key[scancode].spcl = 0; 2832088Ssos for (i=0; i<NUM_STATES; i++) { 2842088Ssos if ((def = get_entry()) == -1) 2852088Ssos return -1; 2862088Ssos if (def & 0x100) 2872088Ssos map->key[scancode].spcl |= (0x80 >> i); 2882088Ssos map->key[scancode].map[i] = def & 0xFF; 2892088Ssos } 2902088Ssos /* get lock state key def */ 29132316Syokota if ((token = yylex()) != TFLAG) 2922088Ssos return -1; 2932088Ssos map->key[scancode].flgs = number; 29432316Syokota token = yylex(); 29532316Syokota return (scancode + 1); 2962088Ssos} 2972088Ssos 29832316Syokotaint 29932316Syokotaget_accent_definition_line(accentmap_t *map) 30032316Syokota{ 30132316Syokota int accent; 30232316Syokota int c1, c2; 30332316Syokota int i; 3042088Ssos 30532316Syokota if (ACC(number) < F_ACC || ACC(number) > L_ACC) 30632316Syokota /* number out of range */ 30732316Syokota return -1; 30832316Syokota accent = number; 30932316Syokota if (map->acc[accent].accchar != 0) { 31032316Syokota /* this entry has already been defined before! */ 31132316Syokota errx(1, "duplicated accent key definition"); 31232316Syokota } 31332316Syokota 31432316Syokota switch ((token = yylex())) { 31532316Syokota case TLET: 31632316Syokota map->acc[accent].accchar = letter; 31732316Syokota break; 31832316Syokota case TNUM: 31932316Syokota map->acc[accent].accchar = number; 32032316Syokota break; 32132316Syokota default: 32232316Syokota return -1; 32332316Syokota } 32432316Syokota 32532316Syokota for (i = 0; (token = yylex()) == '(';) { 32632316Syokota switch ((token = yylex())) { 32732316Syokota case TLET: 32832316Syokota c1 = letter; 32932316Syokota break; 33032316Syokota case TNUM: 33132316Syokota c1 = number; 33232316Syokota break; 33332316Syokota default: 33432316Syokota return -1; 33532316Syokota } 33632316Syokota switch ((token = yylex())) { 33732316Syokota case TLET: 33832316Syokota c2 = letter; 33932316Syokota break; 34032316Syokota case TNUM: 34132316Syokota c2 = number; 34232316Syokota break; 34332316Syokota default: 34432316Syokota return -1; 34532316Syokota } 34632316Syokota if ((token = yylex()) != ')') 34732316Syokota return -1; 34832316Syokota if (i >= NUM_ACCENTCHARS) { 34932316Syokota warnx("too many accented characters, ignored"); 35032316Syokota continue; 35132316Syokota } 35232316Syokota map->acc[accent].map[i][0] = c1; 35332316Syokota map->acc[accent].map[i][1] = c2; 35432316Syokota ++i; 35532316Syokota } 35632316Syokota return (accent + 1); 35732316Syokota} 35832316Syokota 35929603Scharniervoid 3602088Ssosprint_entry(FILE *fp, int value) 3612088Ssos{ 3622088Ssos int val = value & 0xFF; 3632088Ssos 3642088Ssos switch (value) { 3652088Ssos case NOP | 0x100: 3668857Srgrimes fprintf(fp, " nop "); 3672088Ssos break; 3682088Ssos case LSH | 0x100: 3692088Ssos fprintf(fp, " lshift"); 3702088Ssos break; 3712088Ssos case RSH | 0x100: 3722088Ssos fprintf(fp, " rshift"); 3732088Ssos break; 3742088Ssos case CLK | 0x100: 3752088Ssos fprintf(fp, " clock "); 3762088Ssos break; 3772088Ssos case NLK | 0x100: 3782088Ssos fprintf(fp, " nlock "); 3792088Ssos break; 3802088Ssos case SLK | 0x100: 3812088Ssos fprintf(fp, " slock "); 3822088Ssos break; 3832088Ssos case BTAB | 0x100: 3842088Ssos fprintf(fp, " btab "); 3852088Ssos break; 3862088Ssos case LALT | 0x100: 3872088Ssos fprintf(fp, " lalt "); 3882088Ssos break; 3892088Ssos case LCTR | 0x100: 3902088Ssos fprintf(fp, " lctrl "); 3912088Ssos break; 3922088Ssos case NEXT | 0x100: 3932088Ssos fprintf(fp, " nscr "); 3942088Ssos break; 39548105Syokota case PREV | 0x100: 39648105Syokota fprintf(fp, " pscr "); 39748105Syokota break; 3982088Ssos case RCTR | 0x100: 3992088Ssos fprintf(fp, " rctrl "); 4002088Ssos break; 4012088Ssos case RALT | 0x100: 4022088Ssos fprintf(fp, " ralt "); 4032088Ssos break; 4042088Ssos case ALK | 0x100: 4052088Ssos fprintf(fp, " alock "); 4062088Ssos break; 4072088Ssos case ASH | 0x100: 4082088Ssos fprintf(fp, " ashift"); 4092088Ssos break; 4102088Ssos case META | 0x100: 4112088Ssos fprintf(fp, " meta "); 4122088Ssos break; 4132088Ssos case RBT | 0x100: 4142088Ssos fprintf(fp, " boot "); 4152088Ssos break; 4162088Ssos case DBG | 0x100: 4172088Ssos fprintf(fp, " debug "); 4182088Ssos break; 41932316Syokota case SUSP | 0x100: 42032316Syokota fprintf(fp, " susp "); 42132316Syokota break; 42238053Syokota case SPSC | 0x100: 42338053Syokota fprintf(fp, " saver "); 42438053Syokota break; 42554380Syokota case PNC | 0x100: 42654380Syokota fprintf(fp, " panic "); 42754380Syokota break; 42854380Syokota case LSHA | 0x100: 42954380Syokota fprintf(fp, " lshifta"); 43054380Syokota break; 43154380Syokota case RSHA | 0x100: 43254380Syokota fprintf(fp, " rshifta"); 43354380Syokota break; 43454380Syokota case LCTRA | 0x100: 43554380Syokota fprintf(fp, " lctrla"); 43654380Syokota break; 43754380Syokota case RCTRA | 0x100: 43854380Syokota fprintf(fp, " rctrla"); 43954380Syokota break; 44054380Syokota case LALTA | 0x100: 44154380Syokota fprintf(fp, " lalta "); 44254380Syokota break; 44354380Syokota case RALTA | 0x100: 44454380Syokota fprintf(fp, " ralta "); 44554380Syokota break; 44665759Sdwmalone case HALT | 0x100: 44765759Sdwmalone fprintf(fp, " halt "); 44865759Sdwmalone break; 44965759Sdwmalone case PDWN | 0x100: 45065759Sdwmalone fprintf(fp, " pdwn "); 45165759Sdwmalone break; 45274118Sache case PASTE | 0x100: 45374118Sache fprintf(fp, " paste "); 45474118Sache break; 4552088Ssos default: 4562088Ssos if (value & 0x100) { 4578857Srgrimes if (val >= F_FN && val <= L_FN) 4582088Ssos fprintf(fp, " fkey%02d", val - F_FN + 1); 4598857Srgrimes else if (val >= F_SCR && val <= L_SCR) 4602088Ssos fprintf(fp, " scr%02d ", val - F_SCR + 1); 46132316Syokota else if (val >= F_ACC && val <= L_ACC) 46232316Syokota fprintf(fp, " %-6s", acc_names[val - F_ACC]); 4632088Ssos else if (hex) 4648857Srgrimes fprintf(fp, " 0x%02x ", val); 4652088Ssos else 46632316Syokota fprintf(fp, " %3d ", val); 4672088Ssos } 4682088Ssos else { 4692088Ssos if (val < ' ') 4708857Srgrimes fprintf(fp, " %s ", ctrl_names[val]); 4712088Ssos else if (val == 127) 4728857Srgrimes fprintf(fp, " del "); 4739202Srgrimes else if (isascii(val) && isprint(val)) 4748857Srgrimes fprintf(fp, " '%c' ", val); 4752088Ssos else if (hex) 4768857Srgrimes fprintf(fp, " 0x%02x ", val); 4772088Ssos else 4788857Srgrimes fprintf(fp, " %3d ", val); 4792088Ssos } 4802088Ssos } 4812088Ssos} 4822088Ssos 4832088Ssos 4842088Ssosvoid 48542505Syokotaprint_key_definition_line(FILE *fp, int scancode, struct keyent_t *key) 4862088Ssos{ 48729603Scharnier int i; 4882088Ssos 4892088Ssos /* print scancode number */ 4902088Ssos if (hex) 4912088Ssos fprintf(fp, " 0x%02x ", scancode); 4922088Ssos else 4932088Ssos fprintf(fp, " %03d ", scancode); 4942088Ssos 4952088Ssos /* print key definitions */ 4962088Ssos for (i=0; i<NUM_STATES; i++) { 4972088Ssos if (key->spcl & (0x80 >> i)) 4982088Ssos print_entry(fp, key->map[i] | 0x100); 4992088Ssos else 5008857Srgrimes print_entry(fp, key->map[i]); 5012088Ssos } 5022088Ssos 5032088Ssos /* print lock state key def */ 5042088Ssos switch (key->flgs) { 5052088Ssos case 0: 5062088Ssos fprintf(fp, " O\n"); 5072088Ssos break; 5082088Ssos case 1: 5092088Ssos fprintf(fp, " C\n"); 5102088Ssos break; 5112088Ssos case 2: 5122088Ssos fprintf(fp, " N\n"); 5132088Ssos break; 5146046Ssos case 3: 5156046Ssos fprintf(fp, " B\n"); 5166046Ssos break; 5178857Srgrimes } 5182088Ssos} 5192088Ssos 52032316Syokotavoid 52132316Syokotaprint_accent_definition_line(FILE *fp, int accent, struct acc_t *key) 52232316Syokota{ 52332316Syokota int c; 52432316Syokota int i; 5252088Ssos 52632316Syokota if (key->accchar == 0) 52732316Syokota return; 52832316Syokota 52932316Syokota /* print accent number */ 53032316Syokota fprintf(fp, " %-6s", acc_names[accent]); 53132316Syokota if (isascii(key->accchar) && isprint(key->accchar)) 53232316Syokota fprintf(fp, "'%c' ", key->accchar); 53332316Syokota else if (hex) 53432316Syokota fprintf(fp, "0x%02x ", key->accchar); 53532316Syokota else 53632316Syokota fprintf(fp, "%03d ", key->accchar); 53732316Syokota 53832316Syokota for (i = 0; i < NUM_ACCENTCHARS; ++i) { 53932316Syokota c = key->map[i][0]; 54032316Syokota if (c == 0) 54132316Syokota break; 54232316Syokota if ((i > 0) && ((i % 4) == 0)) 54332316Syokota fprintf(fp, "\n "); 54432316Syokota if (isascii(c) && isprint(c)) 54532316Syokota fprintf(fp, "( '%c' ", c); 54632316Syokota else if (hex) 54732316Syokota fprintf(fp, "(0x%02x ", c); 54832316Syokota else 54932316Syokota fprintf(fp, "( %03d ", c); 55032316Syokota c = key->map[i][1]; 55132316Syokota if (isascii(c) && isprint(c)) 55232316Syokota fprintf(fp, "'%c' ) ", c); 55332316Syokota else if (hex) 55432316Syokota fprintf(fp, "0x%02x) ", c); 55532316Syokota else 55632316Syokota fprintf(fp, "%03d ) ", c); 55732316Syokota } 55832316Syokota fprintf(fp, "\n"); 55932316Syokota} 56032316Syokota 5612088Ssosvoid 56232316Syokotadump_entry(int value) 56332316Syokota{ 56432316Syokota if (value & 0x100) { 56532316Syokota value &= 0x00ff; 56632316Syokota switch (value) { 56732316Syokota case NOP: 56832316Syokota printf(" NOP, "); 56932316Syokota break; 57032316Syokota case LSH: 57132316Syokota printf(" LSH, "); 57232316Syokota break; 57332316Syokota case RSH: 57432316Syokota printf(" RSH, "); 57532316Syokota break; 57632316Syokota case CLK: 57732316Syokota printf(" CLK, "); 57832316Syokota break; 57932316Syokota case NLK: 58032316Syokota printf(" NLK, "); 58132316Syokota break; 58232316Syokota case SLK: 58332316Syokota printf(" SLK, "); 58432316Syokota break; 58532316Syokota case BTAB: 58632316Syokota printf(" BTAB, "); 58732316Syokota break; 58832316Syokota case LALT: 58932316Syokota printf(" LALT, "); 59032316Syokota break; 59132316Syokota case LCTR: 59232316Syokota printf(" LCTR, "); 59332316Syokota break; 59432316Syokota case NEXT: 59532316Syokota printf(" NEXT, "); 59632316Syokota break; 59748105Syokota case PREV: 59848105Syokota printf(" PREV, "); 59948105Syokota break; 60032316Syokota case RCTR: 60132316Syokota printf(" RCTR, "); 60232316Syokota break; 60332316Syokota case RALT: 60432316Syokota printf(" RALT, "); 60532316Syokota break; 60632316Syokota case ALK: 60732316Syokota printf(" ALK, "); 60832316Syokota break; 60932316Syokota case ASH: 61032316Syokota printf(" ASH, "); 61132316Syokota break; 61232316Syokota case META: 61332316Syokota printf(" META, "); 61432316Syokota break; 61532316Syokota case RBT: 61632316Syokota printf(" RBT, "); 61732316Syokota break; 61832316Syokota case DBG: 61932316Syokota printf(" DBG, "); 62032316Syokota break; 62132316Syokota case SUSP: 62232316Syokota printf(" SUSP, "); 62332316Syokota break; 62438053Syokota case SPSC: 62538053Syokota printf(" SPSC, "); 62638053Syokota break; 62754380Syokota case PNC: 62854380Syokota printf(" PNC, "); 62954380Syokota break; 63054380Syokota case LSHA: 63154380Syokota printf(" LSHA, "); 63254380Syokota break; 63354380Syokota case RSHA: 63454380Syokota printf(" RSHA, "); 63554380Syokota break; 63654380Syokota case LCTRA: 63754380Syokota printf("LCTRA, "); 63854380Syokota break; 63954380Syokota case RCTRA: 64054380Syokota printf("RCTRA, "); 64154380Syokota break; 64254380Syokota case LALTA: 64354380Syokota printf("LALTA, "); 64454380Syokota break; 64554380Syokota case RALTA: 64654380Syokota printf("RALTA, "); 64754380Syokota break; 64865759Sdwmalone case HALT: 64965759Sdwmalone printf(" HALT, "); 65065759Sdwmalone break; 65165759Sdwmalone case PDWN: 65265759Sdwmalone printf(" PDWN, "); 65365759Sdwmalone break; 65474118Sache case PASTE: 65574118Sache printf("PASTE, "); 65674118Sache break; 65732316Syokota default: 65832316Syokota if (value >= F_FN && value <= L_FN) 65932316Syokota printf(" F(%2d),", value - F_FN + 1); 66032316Syokota else if (value >= F_SCR && value <= L_SCR) 66132486Syokota printf(" S(%2d),", value - F_SCR + 1); 66232316Syokota else if (value >= F_ACC && value <= L_ACC) 66332316Syokota printf(" %-4s, ", acc_names_u[value - F_ACC]); 66432316Syokota else 66532316Syokota printf(" 0x%02X, ", value); 66632316Syokota break; 66732316Syokota } 66832316Syokota } else if (value == '\'') { 66932316Syokota printf(" '\\'', "); 67032316Syokota } else if (value == '\\') { 67132316Syokota printf(" '\\\\', "); 67232316Syokota } else if (isascii(value) && isprint(value)) { 67332316Syokota printf(" '%c', ", value); 67432316Syokota } else { 67532316Syokota printf(" 0x%02X, ", value); 67632316Syokota } 67732316Syokota} 67832316Syokota 67932316Syokotavoid 68032316Syokotadump_key_definition(char *name, keymap_t *keymap) 68132316Syokota{ 68232316Syokota int i, j; 68332316Syokota 68432486Syokota printf("static keymap_t keymap_%s = { 0x%02x, {\n", 68532316Syokota name, (unsigned)keymap->n_keys); 68632316Syokota printf( 68732486Syokota"/* alt\n" 68832486Syokota" * scan cntrl alt alt cntrl\n" 68932486Syokota" * code base shift cntrl shift alt shift cntrl shift spcl flgs\n" 69032316Syokota" * ---------------------------------------------------------------------------\n" 69132316Syokota" */\n"); 69232316Syokota for (i = 0; i < keymap->n_keys; i++) { 69332486Syokota printf("/*%02x*/{{", i); 69432316Syokota for (j = 0; j < NUM_STATES; j++) { 69532316Syokota if (keymap->key[i].spcl & (0x80 >> j)) 69632316Syokota dump_entry(keymap->key[i].map[j] | 0x100); 69732316Syokota else 69832316Syokota dump_entry(keymap->key[i].map[j]); 69932316Syokota } 70032486Syokota printf("}, 0x%02X,0x%02X },\n", 70132316Syokota (unsigned)keymap->key[i].spcl, 70232316Syokota (unsigned)keymap->key[i].flgs); 70332316Syokota } 70432486Syokota printf("} };\n\n"); 70532316Syokota} 70632316Syokota 70732316Syokotavoid 70832316Syokotadump_accent_definition(char *name, accentmap_t *accentmap) 70932316Syokota{ 71032316Syokota int i, j; 71132316Syokota int c; 71232316Syokota 71332486Syokota printf("static accentmap_t accentmap_%s = { %d", 71432316Syokota name, accentmap->n_accs); 71532486Syokota if (accentmap->n_accs <= 0) { 71632486Syokota printf(" };\n\n"); 71732486Syokota return; 71832486Syokota } 71932486Syokota printf(", {\n"); 72032316Syokota for (i = 0; i < NUM_DEADKEYS; i++) { 72132316Syokota printf(" /* %s=%d */\n {", acc_names[i], i); 72232316Syokota c = accentmap->acc[i].accchar; 72332316Syokota if (c == '\'') 72432316Syokota printf(" '\\'', {"); 72532316Syokota else if (c == '\\') 72632316Syokota printf(" '\\\\', {"); 72732316Syokota else if (isascii(c) && isprint(c)) 72832316Syokota printf(" '%c', {", c); 72932316Syokota else if (c == 0) { 73032316Syokota printf(" 0x00 }, \n"); 73132316Syokota continue; 73232316Syokota } else 73332316Syokota printf(" 0x%02x, {", c); 73432316Syokota for (j = 0; j < NUM_ACCENTCHARS; j++) { 73532316Syokota c = accentmap->acc[i].map[j][0]; 73632316Syokota if (c == 0) 73732316Syokota break; 73832316Syokota if ((j > 0) && ((j % 4) == 0)) 73932316Syokota printf("\n\t "); 74032316Syokota if (isascii(c) && isprint(c)) 74132316Syokota printf(" { '%c',", c); 74232316Syokota else 74332316Syokota printf(" { 0x%02x,", c); 74432316Syokota printf("0x%02x },", accentmap->acc[i].map[j][1]); 74532316Syokota } 74632316Syokota printf(" }, },\n"); 74732316Syokota } 74832486Syokota printf("} };\n\n"); 74932316Syokota} 75032316Syokota 75132316Syokotavoid 75219569Sjoergload_keymap(char *opt, int dumponly) 7532088Ssos{ 75432316Syokota keymap_t keymap; 75532316Syokota accentmap_t accentmap; 7562088Ssos FILE *fd; 75776502Ssobomax int i, j; 75819569Sjoerg char *name, *cp; 75976502Ssobomax char *prefix[] = {"", "", KEYMAP_PATH, NULL}; 76076502Ssobomax char *postfix[] = {"", ".kbd", NULL}; 7612088Ssos 76276569Ssobomax cp = getenv("KEYMAP_PATH"); 76376569Ssobomax if (cp != NULL) 76476569Ssobomax asprintf(&(prefix[0]), "%s/", cp); 76576502Ssobomax 76676643Simp fd = NULL; 76776643Simp for (i=0; prefix[i] && fd == NULL; i++) { 76876643Simp for (j=0; postfix[j] && fd == NULL; j++) { 76976502Ssobomax name = mkfullname(prefix[i], opt, postfix[j]); 77076643Simp fd = fopen(name, "r"); 77176502Ssobomax } 77276643Simp } 7732088Ssos if (fd == NULL) { 77429603Scharnier warn("keymap file not found"); 7752088Ssos return; 7762088Ssos } 77732316Syokota memset(&keymap, 0, sizeof(keymap)); 77832316Syokota memset(&accentmap, 0, sizeof(accentmap)); 77932316Syokota token = -1; 7802088Ssos while (1) { 78132316Syokota if (get_definition_line(fd, &keymap, &accentmap) < 0) 7822088Ssos break; 7832088Ssos } 78419569Sjoerg if (dumponly) { 78519569Sjoerg /* fix up the filename to make it a valid C identifier */ 78619569Sjoerg for (cp = opt; *cp; cp++) 78719569Sjoerg if (!isalpha(*cp) && !isdigit(*cp)) *cp = '_'; 78832316Syokota printf("/*\n" 78932316Syokota " * Automatically generated from %s.\n" 79032316Syokota " * DO NOT EDIT!\n" 79132316Syokota " */\n", name); 79232316Syokota dump_key_definition(opt, &keymap); 79332316Syokota dump_accent_definition(opt, &accentmap); 79419569Sjoerg return; 79519569Sjoerg } 79632316Syokota if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) { 79729603Scharnier warn("setting keymap"); 7982088Ssos fclose(fd); 7992088Ssos return; 8002088Ssos } 80132316Syokota if ((accentmap.n_accs > 0) 80232316Syokota && (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) { 80332316Syokota warn("setting accentmap"); 80432316Syokota fclose(fd); 80532316Syokota return; 80632316Syokota } 8072088Ssos} 8082088Ssos 8092088Ssosvoid 8102088Ssosprint_keymap() 8112088Ssos{ 81232316Syokota keymap_t keymap; 81332316Syokota accentmap_t accentmap; 8142088Ssos int i; 8152088Ssos 81632316Syokota if (ioctl(0, GIO_KEYMAP, &keymap) < 0) 81729603Scharnier err(1, "getting keymap"); 81832316Syokota if (ioctl(0, GIO_DEADKEYMAP, &accentmap) < 0) 81932316Syokota memset(&accentmap, 0, sizeof(accentmap)); 8202088Ssos printf( 8212088Ssos"# alt\n" 8222088Ssos"# scan cntrl alt alt cntrl lock\n" 8232088Ssos"# code base shift cntrl shift alt shift cntrl shift state\n" 8242088Ssos"# ------------------------------------------------------------------\n" 8252088Ssos ); 82632316Syokota for (i=0; i<keymap.n_keys; i++) 82732316Syokota print_key_definition_line(stdout, i, &keymap.key[i]); 82832316Syokota 82932316Syokota printf("\n"); 83032316Syokota for (i = 0; i < NUM_DEADKEYS; i++) 83132316Syokota print_accent_definition_line(stdout, i, &accentmap.acc[i]); 83232316Syokota 8332088Ssos} 8342088Ssos 8352088Ssos 8362088Ssosvoid 8372088Ssosload_default_functionkeys() 8382088Ssos{ 8392088Ssos fkeyarg_t fkey; 8402088Ssos int i; 8412088Ssos 8422088Ssos for (i=0; i<NUM_FKEYS; i++) { 8432088Ssos fkey.keynum = i; 8442088Ssos strcpy(fkey.keydef, fkey_table[i]); 8452088Ssos fkey.flen = strlen(fkey_table[i]); 8462088Ssos if (ioctl(0, SETFKEY, &fkey) < 0) 84729603Scharnier warn("setting function key"); 8482088Ssos } 8492088Ssos} 8502088Ssos 8512088Ssosvoid 8522088Ssosset_functionkey(char *keynumstr, char *string) 8532088Ssos{ 8542088Ssos fkeyarg_t fkey; 8552088Ssos 8562088Ssos if (!strcmp(keynumstr, "load") && !strcmp(string, "default")) { 8572088Ssos load_default_functionkeys(); 8582088Ssos return; 8592088Ssos } 8602088Ssos fkey.keynum = atoi(keynumstr); 8612088Ssos if (fkey.keynum < 1 || fkey.keynum > NUM_FKEYS) { 86229603Scharnier warnx("function key number must be between 1 and %d", 8632088Ssos NUM_FKEYS); 8642088Ssos return; 8652088Ssos } 8662088Ssos if ((fkey.flen = strlen(string)) > MAXFK) { 86729603Scharnier warnx("function key string too long (%d > %d)", 8682088Ssos fkey.flen, MAXFK); 8692088Ssos return; 8702088Ssos } 8712088Ssos strcpy(fkey.keydef, string); 8722088Ssos fkey.keynum -= 1; 8732088Ssos if (ioctl(0, SETFKEY, &fkey) < 0) 87429603Scharnier warn("setting function key"); 8752088Ssos} 8762088Ssos 8772088Ssos 8782088Ssosvoid 8792088Ssosset_bell_values(char *opt) 8802088Ssos{ 8815536Ssos int bell, duration, pitch; 8822088Ssos 88338044Syokota bell = 0; 88438044Syokota if (!strncmp(opt, "quiet.", 6)) { 88538044Syokota bell = 2; 88638044Syokota opt += 6; 88738044Syokota } 8888857Srgrimes if (!strcmp(opt, "visual")) 88938044Syokota bell |= 1; 8905536Ssos else if (!strcmp(opt, "normal")) 89138044Syokota duration = 5, pitch = 800; 89248982Syokota else if (!strcmp(opt, "off")) 89348982Syokota duration = 0, pitch = 0; 8942088Ssos else { 8952088Ssos char *v1; 8968857Srgrimes 8975536Ssos bell = 0; 8982088Ssos duration = strtol(opt, &v1, 0); 8992088Ssos if ((duration < 0) || (*v1 != '.')) 9002088Ssos goto badopt; 9012088Ssos opt = ++v1; 9022088Ssos pitch = strtol(opt, &v1, 0); 9032088Ssos if ((pitch < 0) || (*opt == '\0') || (*v1 != '\0')) { 9042088Ssosbadopt: 90529603Scharnier warnx("argument to -b must be DURATION.PITCH"); 9062088Ssos return; 9072088Ssos } 90838044Syokota if (pitch != 0) 90938044Syokota pitch = 1193182 / pitch; /* in Hz */ 91038044Syokota duration /= 10; /* in 10 m sec */ 9112088Ssos } 9122088Ssos 9135536Ssos ioctl(0, CONS_BELLTYPE, &bell); 91438044Syokota if ((bell & ~2) == 0) 9155536Ssos fprintf(stderr, "[=%d;%dB", pitch, duration); 9162088Ssos} 9172088Ssos 9182088Ssos 9192088Ssosvoid 9202088Ssosset_keyrates(char *opt) 9212088Ssos{ 92244628Syokota int arg[2]; 92339047Syokota int repeat; 92439047Syokota int delay; 92546761Syokota int r, d; 9262088Ssos 92746761Syokota if (!strcmp(opt, "slow")) { 92844628Syokota delay = 1000, repeat = 500; 92946761Syokota d = 3, r = 31; 93046761Syokota } else if (!strcmp(opt, "normal")) { 93144628Syokota delay = 500, repeat = 125; 93246761Syokota d = 1, r = 15; 93346761Syokota } else if (!strcmp(opt, "fast")) { 93439047Syokota delay = repeat = 0; 93546761Syokota d = r = 0; 93646761Syokota } else { 9372088Ssos int n; 9382088Ssos char *v1; 9392088Ssos 9402088Ssos delay = strtol(opt, &v1, 0); 9412088Ssos if ((delay < 0) || (*v1 != '.')) 9422088Ssos goto badopt; 9432088Ssos opt = ++v1; 9442088Ssos repeat = strtol(opt, &v1, 0); 9452088Ssos if ((repeat < 0) || (*opt == '\0') || (*v1 != '\0')) { 9462088Ssosbadopt: 94729603Scharnier warnx("argument to -r must be delay.repeat"); 9482088Ssos return; 9492088Ssos } 95046761Syokota for (n = 0; n < ndelays - 1; n++) 95146761Syokota if (delay <= delays[n]) 95246761Syokota break; 95346761Syokota d = n; 95446761Syokota for (n = 0; n < nrepeats - 1; n++) 95546761Syokota if (repeat <= repeats[n]) 95646761Syokota break; 95746761Syokota r = n; 9582088Ssos } 9592088Ssos 96044628Syokota arg[0] = delay; 96144628Syokota arg[1] = repeat; 96246761Syokota if (ioctl(0, KDSETREPEAT, arg)) { 96346761Syokota if (ioctl(0, KDSETRAD, (d << 5) | r)) 96446761Syokota warn("setting keyboard rate"); 96546761Syokota } 9662088Ssos} 9672088Ssos 9682088Ssos 9696046Ssosvoid 9706046Ssosset_history(char *opt) 9716046Ssos{ 9726046Ssos int size; 9736046Ssos 9746046Ssos size = atoi(opt); 9756046Ssos if ((*opt == '\0') || size < 0) { 97629603Scharnier warnx("argument must be a positive number"); 9776046Ssos return; 9786046Ssos } 9796046Ssos if (ioctl(0, CONS_HISTORY, &size) == -1) 98029603Scharnier warn("setting history buffer size"); 9816046Ssos} 9826046Ssos 98342505Syokotastatic char 98442505Syokota*get_kbd_type_name(int type) 98542505Syokota{ 98642505Syokota static struct { 98742505Syokota int type; 98842505Syokota char *name; 98942505Syokota } name_table[] = { 99042505Syokota { KB_84, "AT 84" }, 99142505Syokota { KB_101, "AT 101/102" }, 99242505Syokota { KB_OTHER, "generic" }, 99342505Syokota }; 99442505Syokota int i; 9956046Ssos 99642505Syokota for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 99742505Syokota if (type == name_table[i].type) 99842505Syokota return name_table[i].name; 99942505Syokota } 100042505Syokota return "unknown"; 100142505Syokota} 100242505Syokota 100342505Syokotavoid 100442505Syokotashow_kbd_info(void) 100542505Syokota{ 100642505Syokota keyboard_info_t info; 100742505Syokota 100842505Syokota if (ioctl(0, KDGKBINFO, &info) == -1) { 100942505Syokota warn("unable to obtain keyboard information"); 101042505Syokota return; 101142505Syokota } 101242505Syokota printf("kbd%d:\n", info.kb_index); 101342505Syokota printf(" %.*s%d, type:%s (%d)\n", 101442505Syokota sizeof(info.kb_name), info.kb_name, info.kb_unit, 101542505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 101642505Syokota} 101742505Syokota 101842505Syokota 101942505Syokotavoid 102042505Syokotaset_keyboard(char *device) 102142505Syokota{ 102242505Syokota keyboard_info_t info; 102342505Syokota int fd; 102442505Syokota 102542505Syokota fd = open(device, O_RDONLY); 102642505Syokota if (fd < 0) { 102742505Syokota warn("cannot open %s", device); 102842505Syokota return; 102942505Syokota } 103042505Syokota if (ioctl(fd, KDGKBINFO, &info) == -1) { 103142505Syokota warn("unable to obtain keyboard information"); 103242505Syokota close(fd); 103342505Syokota return; 103442505Syokota } 103542505Syokota /* 103642505Syokota * The keyboard device driver won't release the keyboard by 103742505Syokota * the following ioctl, but it automatically will, when the device 103842505Syokota * is closed. So, we don't check error here. 103942505Syokota */ 104042505Syokota ioctl(fd, CONS_RELKBD, 0); 104142505Syokota close(fd); 104242505Syokota#if 1 104342505Syokota printf("kbd%d\n", info.kb_index); 104442505Syokota printf(" %.*s%d, type:%s (%d)\n", 104542505Syokota sizeof(info.kb_name), info.kb_name, info.kb_unit, 104642505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 104742505Syokota#endif 104842505Syokota 104942505Syokota if (ioctl(0, CONS_SETKBD, info.kb_index) == -1) 105042505Syokota warn("unable to set keyboard"); 105142505Syokota} 105242505Syokota 105342505Syokota 105442505Syokotavoid 105542505Syokotarelease_keyboard(void) 105642505Syokota{ 105742505Syokota keyboard_info_t info; 105842505Syokota 105942505Syokota /* 106042505Syokota * If stdin is not associated with a keyboard, the following ioctl 106142505Syokota * will fail. 106242505Syokota */ 106342505Syokota if (ioctl(0, KDGKBINFO, &info) == -1) { 106442505Syokota warn("unable to obtain keyboard information"); 106542505Syokota return; 106642505Syokota } 106742505Syokota#if 1 106842505Syokota printf("kbd%d\n", info.kb_index); 106942505Syokota printf(" %.*s%d, type:%s (%d)\n", 107042505Syokota sizeof(info.kb_name), info.kb_name, info.kb_unit, 107142505Syokota get_kbd_type_name(info.kb_type), info.kb_type); 107242505Syokota#endif 107342505Syokota if (ioctl(0, CONS_RELKBD, 0) == -1) 107442505Syokota warn("unable to release the keyboard"); 107542505Syokota} 107642505Syokota 107742505Syokota 107829603Scharnierstatic void 10792088Ssosusage() 10802088Ssos{ 108129603Scharnier fprintf(stderr, "%s\n%s\n%s\n", 108242505Syokota"usage: kbdcontrol [-dFKix] [-b duration.pitch | [quiet.]belltype]", 108329603Scharnier" [-r delay.repeat | speed] [-l mapfile] [-f # string]", 108442505Syokota" [-h size] [-k device] [-L mapfile]"); 108529603Scharnier exit(1); 10862088Ssos} 10872088Ssos 10882088Ssos 108951287Speterint 10902088Ssosmain(int argc, char **argv) 10912088Ssos{ 10922088Ssos int opt; 10932088Ssos 109442505Syokota while((opt = getopt(argc, argv, "b:df:h:iKk:Fl:L:r:x")) != -1) 10952088Ssos switch(opt) { 10962088Ssos case 'b': 10972088Ssos set_bell_values(optarg); 10982088Ssos break; 10992088Ssos case 'd': 11002088Ssos print_keymap(); 11012088Ssos break; 11022088Ssos case 'l': 110319569Sjoerg load_keymap(optarg, 0); 11042088Ssos break; 110519569Sjoerg case 'L': 110619569Sjoerg load_keymap(optarg, 1); 110719569Sjoerg break; 11082088Ssos case 'f': 11098857Srgrimes set_functionkey(optarg, 11102088Ssos nextarg(argc, argv, &optind, 'f')); 11112088Ssos break; 11122088Ssos case 'F': 11132088Ssos load_default_functionkeys(); 11142088Ssos break; 11156046Ssos case 'h': 11166046Ssos set_history(optarg); 11176046Ssos break; 111842505Syokota case 'i': 111942505Syokota show_kbd_info(); 112042505Syokota break; 112142505Syokota case 'K': 112242505Syokota release_keyboard(); 112342505Syokota break; 112442505Syokota case 'k': 112542505Syokota set_keyboard(optarg); 112642505Syokota break; 11272088Ssos case 'r': 11282088Ssos set_keyrates(optarg); 11292088Ssos break; 11302088Ssos case 'x': 11312088Ssos hex = 1; 11322088Ssos break; 11332088Ssos default: 11342088Ssos usage(); 11352088Ssos } 113629603Scharnier if ((optind != argc) || (argc == 1)) 11372088Ssos usage(); 11382088Ssos exit(0); 11392088Ssos} 1140