kbdtest3.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. char *revision = "3.37";
  2. /*+-----------------------------------------------------------------------
  3. kbdtest3.c -- test keyboard values
  4. wht@wht.net
  5. See ecu manual section titled Function Key Recognition
  6. Defined functions:
  7. dump_putc(ch)
  8. dump_puts(str)
  9. hex_dump16(int16)
  10. hex_dump32(int32)
  11. hex_dump4(int4)
  12. hex_dump8(int8)
  13. hex_dump_fp(fp, str, len, title, terse_flag)
  14. k3ttymode(arg)
  15. main(argc, argv)
  16. read_kbd_string(buf, maxsize)
  17. termio_parity_text(cflag)
  18. tputstrs(strs)
  19. write_funckeymap_desc(fp, buf, buflen, name)
  20. xtoasc(ch, incl_3char)
  21. ------------------------------------------------------------------------*/
  22. /*+:EDITS:*/
  23. /*:04-26-2000-11:16-wht@bob-RELEASE 4.42 */
  24. /*:02-26-1998-03:10-wht@kepler-fix some warnings: fidget */
  25. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  26. /*:09-11-1996-20:00-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  27. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  28. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  29. /*:10-15-1995-15:31-wht@jonah-must use TERMIO too now */
  30. /*:01-12-1995-15:20-wht@n4hgf-apply Andrew Chernov 8-bit clean+FreeBSD patch */
  31. /*:11-16-1994-19:50-wht@n4hgf-xtoasc call had only 1 arg */
  32. /*:05-04-1994-04:39-wht@n4hgf-ECU release 3.30 */
  33. /*:01-11-1994-15:37-wht@n4hgf-remove explicit paths from stty and sed */
  34. /*:09-10-1992-13:59-wht@n4hgf-ECU release 3.20 */
  35. /*:08-22-1992-15:39-wht@n4hgf-ECU release 3.20 BETA */
  36. /*:04-19-1992-20:59-wht@n4hgf-nonansikeys to funckeymap */
  37. /*:02-22-1992-12:46-root@n4hgf-thank markd@phoenix.pub.uu.oz.au for typo fix */
  38. /*:01-06-1992-17:56-wht@tridom-much more error checking */
  39. /*:01-06-1992-17:56-wht@tridom-eliminate sun stty - causes problems */
  40. /*:08-28-1991-14:07-wht@n4hgf2-SVR4 cleanup by aega84!lh */
  41. /*:08-17-1991-13:58-root@n4hgf-make kbd entirely raw */
  42. /*:08-06-1991-13:12-wht@n4hgf-add parity reporting */
  43. /*:08-06-1991-13:12-wht@n4hgf-some terminals reinvent parity bit's use */
  44. /*:07-25-1991-12:58-wht@n4hgf-ECU release 3.10 */
  45. /*:04-29-1991-18:24-wht@n4hgf-let us see what keyboards say */
  46. #include <stdio.h>
  47. #include <signal.h>
  48. #include <ctype.h>
  49. #include <sys/errno.h>
  50. #include <string.h>
  51. #include "ecu_config.h"
  52. #include "ecu_types.h"
  53. #include "ecu_stat.h"
  54. #include "ecutermio.h"
  55. char *ctime();
  56. char *getenv();
  57. #define VMIN_VALUE 32
  58. #define VTIME_VALUE 2
  59. #define TTYIN 0 /* mnemonic */
  60. #define TTYOUT 1 /* mnemonic */
  61. #define TTYERR 2 /* mnemonic */
  62. struct TERMIO lv; /* attributes for the line to remote */
  63. struct TERMIO tv0; /* for saving, changing TTY atributes */
  64. struct TERMIO tv; /* for saving, changing TTY atributes */
  65. char *strs_intro[] =
  66. {
  67. "\n",
  68. "Let's learn your keyboard. I'll be making a file named kbdtest3.out\n",
  69. "For each of the key names shown below, please press the key and wait.\n",
  70. "\n",
  71. "If you do not have a key on your keyboard, make an alternate choice\n",
  72. "or press the space bar if nothing seems reasonable.\n",
  73. "\n",
  74. "If you press a key but don't see further activity after a second or two\n",
  75. "press the slash '/' key unless you can choose a reasonable alternate.\n",
  76. "Keys which produce duplicate the keystroke sequence of other keys are\n",
  77. "not acceptable.\n",
  78. "\n",
  79. "Do not use the same key for more than one function.\n",
  80. "\n",
  81. (char *)0
  82. };
  83. char *strs_thanks[] =
  84. {
  85. "\n",
  86. "Thank you. If you wish to mail me the contents of kbdtest3.out,\n",
  87. "please include a detailed description of the system and software\n",
  88. "(i.e., \"Metrolink xterm keyboard on SCO 3.2r2\")\n",
  89. "(I WANT you to mail me results for non-SCO/non-ISC-console keyboards.)\n",
  90. "If you had to hack this program, mail it in its entirety as well.\n",
  91. "\n",
  92. "My address: wht@wht.net\n",
  93. (char *)0
  94. };
  95. char *strs_bktab[] =
  96. {
  97. "You'll have to pick another function key (like F11?). If you are\n",
  98. "using an xterm here perhaps a <Shift>Tab VT100 override will help.\n",
  99. (char *)0
  100. };
  101. struct keystruc
  102. {
  103. char *ecuname;
  104. char *peoplename;
  105. int count;
  106. unsigned char str[VMIN_VALUE + 1];
  107. };
  108. struct keystruc need_names[] =
  109. {
  110. {"BkTab", "Back Tab (Shift Tab)"}, /* 0 */
  111. {"CU5", "Unshifted Keypad 5"}, /* 1 */
  112. {"F1", "F1"}, /* 2 */
  113. {"F2", "F2"}, /* 3 */
  114. {"F3", "F3"}, /* 4 */
  115. {"F4", "F4"}, /* 5 */
  116. {"F5", "F5"}, /* 6 */
  117. {"F6", "F6"}, /* 7 */
  118. {"F7", "F7"}, /* 8 */
  119. {"F8", "F8"}, /* 9 */
  120. {"F9", "F9"}, /* 10 */
  121. {"F10", "F10"}, /* 11 */
  122. {"F11", "F11"}, /* 12 */
  123. {"F12", "F12"}, /* 13 */
  124. {"Ins", "Ins"}, /* 14 */
  125. #define I_HOME 15
  126. {"Home", "Home"}, /* 15 */
  127. #define I_END 16
  128. {"End", "End"}, /* 16 */
  129. {"PgUp", "PgUp"}, /* 17 */
  130. {"PgDn", "PgDn"}, /* 18 */
  131. {"CUU", "Cursor Up"}, /* 19 */
  132. {"CUD", "Cursor Down"}, /* 21 */
  133. {"CUL", "Cursor Left"}, /* 22 */
  134. {"CUR", "Cursor Right"}, /* 23 */
  135. {(char *)0, (char *)0}
  136. };
  137. char *parity_text = "<undetermined>";
  138. static FILE *dumpfp;
  139. /*+-------------------------------------------------------------------------
  140. dump_putc(ch)
  141. --------------------------------------------------------------------------*/
  142. void
  143. dump_putc(ch)
  144. char ch;
  145. {
  146. fputc(ch, dumpfp);
  147. } /* end of dump_putc */
  148. /*+-------------------------------------------------------------------------
  149. dump_puts(str)
  150. --------------------------------------------------------------------------*/
  151. void
  152. dump_puts(str)
  153. char *str;
  154. {
  155. fputs(str, dumpfp);
  156. } /* end of dump_puts */
  157. /*+-----------------------------------------------------------------------
  158. hex_dump#... subservient routines
  159. ------------------------------------------------------------------------*/
  160. void
  161. hex_dump4(int4)
  162. unsigned char int4;
  163. {
  164. int4 &= 15;
  165. dump_putc((int4 >= 10) ? (int4 + 'A' - 10) : (int4 + '0'));
  166. }
  167. void
  168. hex_dump8(int8)
  169. unsigned char int8;
  170. {
  171. hex_dump4(int8 >> 4);
  172. hex_dump4(int8);
  173. }
  174. void
  175. hex_dump16(int16)
  176. unsigned short int16;
  177. {
  178. hex_dump8(int16 >> 8);
  179. hex_dump8(int16);
  180. }
  181. void
  182. hex_dump32(int32)
  183. unsigned long int32;
  184. {
  185. hex_dump16(int32 >> 16);
  186. hex_dump16(int32);
  187. }
  188. /*+-----------------------------------------------------------------
  189. hex_dump_fp(fp,str,len,title,terse_flag)
  190. if 'title' not NULL, title is printed... 'terse_flag'
  191. controls whether or not the title is "conspicuous" with
  192. hyphens before and after it making title line >70 chars long
  193. ------------------------------------------------------------------*/
  194. void
  195. hex_dump_fp(fp, str, len, title, terse_flag)
  196. FILE *fp;
  197. char *str;
  198. int len;
  199. char *title;
  200. int terse_flag;
  201. {
  202. int istr;
  203. int ipos = 0;
  204. int itmp;
  205. dumpfp = fp;
  206. if (title && (istr = strlen(title)))
  207. {
  208. if (!terse_flag)
  209. {
  210. ipos = (73 - istr) / 2;
  211. itmp = ipos;
  212. while (itmp--)
  213. dump_putc('-');
  214. dump_putc(' ');
  215. if (istr & 1)
  216. ipos--;
  217. }
  218. dump_puts(title);
  219. if (!terse_flag)
  220. {
  221. dump_putc(' ');
  222. while (ipos--)
  223. dump_putc('-');
  224. }
  225. dump_puts("\n");
  226. }
  227. istr = 0;
  228. while (istr < len)
  229. {
  230. hex_dump16(istr);
  231. dump_putc(' ');
  232. for (itmp = 0; itmp < 16; ++itmp)
  233. {
  234. ipos = istr + itmp;
  235. if (ipos >= len)
  236. {
  237. if (!terse_flag)
  238. dump_puts(" ");
  239. continue;
  240. }
  241. dump_putc(' ');
  242. hex_dump8(str[ipos]);
  243. }
  244. dump_puts(" | ");
  245. for (itmp = 0; itmp < 16; ++itmp)
  246. {
  247. ipos = istr + itmp;
  248. if ((ipos) >= len)
  249. {
  250. if (!terse_flag)
  251. dump_putc(' ');
  252. }
  253. else
  254. {
  255. dump_putc((str[ipos] >= ' ' && str[ipos] < 0x7f)
  256. ? str[ipos] : '.');
  257. }
  258. }
  259. if (dumpfp == stdout)
  260. dump_puts(" |\r\n");
  261. else
  262. dump_puts(" |\n");
  263. istr += 16;
  264. } /* end of while(istr < len) */
  265. } /* end of hex_dump_fp */
  266. /*+-----------------------------------------------------------------------
  267. xtoasc(character) - Make all chars "printable"
  268. returns pointer to a static string containing printable version
  269. of a character. If control char, printed as "^A", etc.
  270. if incl_3char set true, then space + ASCII assignment (e.g. "NUL") is
  271. appended to the string for non-printable graphics
  272. ------------------------------------------------------------------------*/
  273. char *
  274. xtoasc(ch)
  275. unsigned char ch;
  276. {
  277. static char gg[8];
  278. char *ascii_ctlstr =
  279. "nulsohstxetxeotenqackbelbs ht nl vt ff cr so si dle\
  280. dc1dc2dc3dc4naksynetbcanem subescfs gs rs us sp ";
  281. if (ch == 0x7F)
  282. strcpy(gg, "del");
  283. else if (ch == 0x9b)
  284. strcpy(gg, "csi");
  285. else if (ch > 0x7F)
  286. sprintf(gg, "0x%02x", (unsigned char)ch);
  287. else if (ch > 0x20)
  288. {
  289. gg[0] = ch;
  290. gg[1] = 0;
  291. }
  292. else
  293. {
  294. strncpy(gg, ascii_ctlstr + (ch * 3), 3);
  295. gg[3] = 0;
  296. }
  297. return (gg);
  298. } /* end of xtoasc */
  299. /*+-------------------------------------------------------------------------
  300. write_funckeymap_desc(fp,buf,buflen,name)
  301. --------------------------------------------------------------------------*/
  302. void
  303. write_funckeymap_desc(fp, buf, buflen, name)
  304. FILE *fp;
  305. unsigned char *buf;
  306. int buflen;
  307. char *name;
  308. {
  309. char s256[256];
  310. sprintf(s256, " %s:%s:", name, name);
  311. while (strlen(s256) < (unsigned)20)
  312. strcat(s256, " ");
  313. while (buflen--)
  314. {
  315. strcat(s256, xtoasc(*buf++, 0));
  316. if (buflen)
  317. strcat(s256, " ");
  318. }
  319. strcat(s256, "\n");
  320. fputs(s256, fp);
  321. } /* end of write_funckeymap_desc */
  322. /*+-------------------------------------------------------------------------
  323. tputstrs(strs)
  324. --------------------------------------------------------------------------*/
  325. void
  326. tputstrs(strs)
  327. char **strs;
  328. {
  329. while (*strs)
  330. fputs(*strs++, stdout);
  331. } /* end of tputstrs */
  332. /*+-----------------------------------------------------------------------
  333. k3ttymode(arg) -- control user console (kbd/screen)
  334. Where arg ==
  335. 0 restore attributes saved at start of execution
  336. 1 raw mode
  337. ------------------------------------------------------------------------*/
  338. void
  339. k3ttymode(arg)
  340. int arg;
  341. {
  342. if (arg)
  343. {
  344. (void)ecugetattr(TTYIN, &tv);
  345. tv.c_cflag &= ~(CS8 | PARENB | PARODD);
  346. tv.c_cflag |= CS8;
  347. tv.c_iflag &= ~(INLCR | ICRNL | IGNCR | IXOFF | ISTRIP);
  348. #if defined(IUCLC)
  349. tv.c_iflag &= ~IUCLC;
  350. #endif
  351. tv.c_lflag &= ~(ICANON | ISIG | ECHO);
  352. tv.c_cc[VEOF] = '\01';
  353. tv.c_cc[VEOL] = '\0';
  354. tv.c_cc[VMIN] = VMIN_VALUE;
  355. tv.c_cc[VTIME] = VTIME_VALUE;
  356. (void)ecusetattr(TTYIN, TCSETAW, &tv);
  357. }
  358. else
  359. (void)ecusetattr(TTYIN, TCSETAW, &tv0);
  360. }
  361. /*+-------------------------------------------------------------------------
  362. read_kbd_string(buf,max)
  363. --------------------------------------------------------------------------*/
  364. int
  365. read_kbd_string(buf, maxsize)
  366. unsigned char *buf;
  367. int maxsize;
  368. {
  369. int count = read(TTYIN, buf, maxsize);
  370. return (count);
  371. } /* end of read_kbd_string */
  372. /*+-------------------------------------------------------------------------
  373. termio_parity_text(cflag)
  374. --------------------------------------------------------------------------*/
  375. char *
  376. termio_parity_text(cflag)
  377. int cflag;
  378. {
  379. return ((cflag & PARENB) ? ((cflag & PARODD) ? "odd" : "even") : "none");
  380. } /* end of termio_parity_text */
  381. /*+-----------------------------------------------------------------------
  382. main()
  383. ------------------------------------------------------------------------*/
  384. void
  385. main(argc, argv)
  386. int argc;
  387. char **argv;
  388. {
  389. int itmp;
  390. int count;
  391. int got_ctrl;
  392. int found_dup;
  393. int unusable = 0;
  394. char ch;
  395. char *ttype;
  396. char *cp;
  397. struct keystruc *key = need_names;
  398. struct keystruc *key2;
  399. unsigned char instr[VMIN_VALUE + 1];
  400. #if !defined(sun)
  401. char s128[128];
  402. #endif
  403. FILE *fpout;
  404. long now;
  405. int errflg = 0;
  406. char *outfile = "kbdtest3.out";
  407. /* extern char *optarg; */
  408. extern int optind;
  409. setbuf(stdout, NULL);
  410. setbuf(stderr, NULL);
  411. while ((itmp = getopt(argc, argv, "")) != -1)
  412. {
  413. switch (itmp)
  414. {
  415. case '?':
  416. errflg++;
  417. }
  418. }
  419. if (optind == (argc - 1))
  420. outfile = argv[optind++];
  421. if (errflg || (optind != argc))
  422. {
  423. (void)fprintf(stderr, "usage: kbdtest3 [-hx] [outfile]\n");
  424. exit(1);
  425. }
  426. printf("\n\n\necu kbdtest3 revision %s\n", revision);
  427. tputstrs(strs_intro);
  428. if (!(fpout = fopen(outfile, "a")))
  429. {
  430. perror(outfile);
  431. exit(1);
  432. }
  433. ecugetattr(TTYIN, &tv0); /* get original status */
  434. parity_text = termio_parity_text(tv0.c_cflag);
  435. if (!(ttype = getenv("TERM")))
  436. ttype = "??";
  437. time(&now);
  438. fprintf(fpout, "# funckeymap for '%s' under ", ttype);
  439. #if defined(M_SYSV) || defined(SCO32v5)
  440. fputs("SCO\n", fpout);
  441. #else
  442. #if defined(ISC)
  443. fputs("ISC\n", fpout);
  444. #else
  445. #if defined(MOTSVR3)
  446. fputs("MotSVR3\n", fpout);
  447. #else
  448. #if defined(sun)
  449. fputs("SunOS\n", fpout);
  450. #else
  451. #if defined(__FreeBSD__)
  452. fputs("FreeBSD\n", fpout);
  453. #else
  454. fputs("??? OS\n", fpout);
  455. #endif /* __FreeBSD__ */
  456. #endif /* sun */
  457. #endif /* MOTSVR3 */
  458. #endif /* ISC */
  459. #endif /* M_SYSV */
  460. fprintf(fpout, "# built by kbdtest3 %s %s", revision, ctime(&now));
  461. fprintf(fpout, "# keyboard parity required = %s\n", parity_text);
  462. #if !defined(sun)
  463. fprintf(fpout, "# stty -a at kbdtest3 execution time:\n");
  464. fclose(fpout);
  465. strcpy(s128, "stty -a | sed -e 's/^/# /' >> ");
  466. strcat(s128, outfile);
  467. system(s128);
  468. if (!(fpout = fopen(outfile, "a")))
  469. {
  470. perror(outfile);
  471. exit(1);
  472. }
  473. #endif
  474. fprintf(fpout, "%s\n", ttype);
  475. printf("Your keyboard driver parity is set to %s\n", parity_text);
  476. printf("press ^D (0x04) to terminate program early\n\n");
  477. k3ttymode(1);
  478. while (key->ecuname)
  479. {
  480. key->count = -1;
  481. printf("%-20.20s: ", key->peoplename);
  482. count = read_kbd_string(instr, VMIN_VALUE);
  483. if (!count)
  484. {
  485. printf("whoops ..... zero length read\n");
  486. break;
  487. }
  488. if (!count)
  489. {
  490. perror("keyboard");
  491. break;
  492. }
  493. if (!strcmp(key->ecuname, "BkTab") && (count == 1) &&
  494. (instr[0] == 9))
  495. {
  496. printf("produced the same keystroke sequence as TAB\n");
  497. tputstrs(strs_bktab);
  498. continue;
  499. }
  500. if ((count == 1) && ((instr[0] & 0x7F) == 4))
  501. {
  502. printf("--abort--\n");
  503. fputs("# User aborted entry.\n", fpout);
  504. unusable = 2;
  505. goto DONE;
  506. }
  507. if ((count == 1) && (instr[0] == '/'))
  508. {
  509. printf("--dead key--\n");
  510. fprintf(fpout, "# %s: dead key and no reasonable alternate\n",
  511. key->ecuname);
  512. }
  513. else if ((count == 1) && (instr[0] == ' '))
  514. {
  515. printf("--no key--\n");
  516. fprintf(fpout, "# %s: no key and no reasonable alternate\n",
  517. key->ecuname);
  518. }
  519. else
  520. {
  521. for (itmp = 0; itmp < count; itmp++)
  522. printf("%02x ", instr[itmp]);
  523. fputc(' ', stdout);
  524. got_ctrl = 0;
  525. for (itmp = 0; itmp < count; itmp++)
  526. {
  527. ch = instr[itmp] & 0x7F;
  528. if ((ch < ' ') || (ch > '~'))
  529. ch = '.', got_ctrl = 1;
  530. fputc(ch, stdout);
  531. }
  532. printf("\n");
  533. key->count = count;
  534. memcpy(key->str, instr, sizeof(key->str));
  535. write_funckeymap_desc(fpout, (unsigned char *)instr, count,
  536. key->ecuname);
  537. if (!got_ctrl)
  538. {
  539. printf("This looks like a printable character string.\n");
  540. printf("You might want to reconsider another key.\n");
  541. fprintf(fpout, "# the above entry is suspect\n");
  542. }
  543. }
  544. key++;
  545. }
  546. printf("\n");
  547. /*
  548. * check for dup sequences
  549. */
  550. found_dup = 0;
  551. for (key = need_names, key2 = key + 1;; key2++)
  552. {
  553. if (!key2->ecuname)
  554. {
  555. key++;
  556. if (!key->ecuname)
  557. break;
  558. key2 = key + 1;
  559. if (!key2->ecuname)
  560. break;
  561. }
  562. if ((key->count < 0) || (key2->count < 0) || (key->count != key2->count))
  563. continue;
  564. if (!memcmp(key->str, key2->str, key->count))
  565. {
  566. printf("'%s' and '%s' produced the same key sequence\n",
  567. key->peoplename, key2->peoplename);
  568. found_dup++;
  569. }
  570. }
  571. if (found_dup)
  572. {
  573. fprintf(fpout,
  574. "# found %d keystroke sequence duplication(s)\n", found_dup);
  575. unusable = 1;
  576. }
  577. if (need_names[I_HOME].count < 0)
  578. {
  579. cp = "# No Home key was successfully defined!\n";
  580. printf(cp + 2);
  581. fprintf(fpout, cp);
  582. unusable = 1;
  583. }
  584. if (need_names[I_END].count < 0)
  585. {
  586. cp = "# No End key was successfully defined!\n";
  587. printf(cp + 2);
  588. fprintf(fpout, cp);
  589. unusable = 1;
  590. }
  591. DONE:
  592. if (unusable)
  593. {
  594. printf("\nThis will be unusable. Please try again.\n");
  595. fprintf(fpout, "# above entry is unusable\n");
  596. }
  597. else
  598. {
  599. printf("\nRemember to set keyboard parity to \"%s\" ",
  600. parity_text);
  601. fputs("when using this entry.\n", stdout);
  602. tputstrs(strs_thanks);
  603. }
  604. fputs("\n", fpout);
  605. fclose(fpout);
  606. k3ttymode(0);
  607. exit(0);
  608. } /* end of main */
  609. /* vi: set tabstop=4 shiftwidth=4: */