12490Sjkh/* 22490Sjkh * Copyright (c) 1988, 1993 32490Sjkh * The Regents of the University of California. All rights reserved. 42490Sjkh * 52490Sjkh * Redistribution and use in source and binary forms, with or without 62490Sjkh * modification, are permitted provided that the following conditions 72490Sjkh * are met: 82490Sjkh * 1. Redistributions of source code must retain the above copyright 92490Sjkh * notice, this list of conditions and the following disclaimer. 102490Sjkh * 2. Redistributions in binary form must reproduce the above copyright 112490Sjkh * notice, this list of conditions and the following disclaimer in the 122490Sjkh * documentation and/or other materials provided with the distribution. 13203932Simp * 3. Neither the name of the University nor the names of its contributors 142490Sjkh * may be used to endorse or promote products derived from this software 152490Sjkh * without specific prior written permission. 162490Sjkh * 172490Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 182490Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 192490Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 202490Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 212490Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 222490Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 232490Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 242490Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 252490Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 262490Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 272490Sjkh * SUCH DAMAGE. 282490Sjkh */ 292490Sjkh 3010352Sjoerg/* 31179654Sscf * Taught to send *real* morse by Lyndon Nerenberg (VE6BBM) 32179654Sscf * <lyndon@orthanc.ca> 3310352Sjoerg */ 3410352Sjoerg 352490Sjkh#ifndef lint 3653920Sbillfstatic const char copyright[] = 372490Sjkh"@(#) Copyright (c) 1988, 1993\n\ 382490Sjkh The Regents of the University of California. All rights reserved.\n"; 392490Sjkh#endif /* not lint */ 402490Sjkh 412490Sjkh#ifndef lint 4253920Sbillf#if 0 432490Sjkhstatic char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 4453920Sbillf#endif 4553920Sbillfstatic const char rcsid[] = 4653920Sbillf "$FreeBSD$"; 472490Sjkh#endif /* not lint */ 482490Sjkh 4957527Sjoerg#include <sys/time.h> 5057527Sjoerg 512490Sjkh#include <ctype.h> 5257527Sjoerg#include <fcntl.h> 5378793Sache#include <langinfo.h> 5410352Sjoerg#include <locale.h> 5557527Sjoerg#include <signal.h> 5657527Sjoerg#include <stdio.h> 5710352Sjoerg#include <stdlib.h> 5835857Sjb#include <string.h> 5957527Sjoerg#include <termios.h> 6054622Sbillf#include <unistd.h> 612490Sjkh 62203479Simp/* Always use the speaker, let the open fail if -p is selected */ 63203479Simp#define SPEAKER "/dev/speaker" 64203479Simp 6510352Sjoerg#ifdef SPEAKER 66152306Sru#include <dev/speaker/speaker.h> 6710352Sjoerg#endif 6810352Sjoerg 6910352Sjoergstruct morsetab { 70203921Suqs const char inchar; 71203921Suqs const char *morse; 722490Sjkh}; 732490Sjkh 7454622Sbillfstatic const struct morsetab mtab[] = { 752490Sjkh 7610352Sjoerg /* letters */ 7710352Sjoerg 7854622Sbillf {'a', ".-"}, 7954622Sbillf {'b', "-..."}, 8054622Sbillf {'c', "-.-."}, 8154622Sbillf {'d', "-.."}, 8254622Sbillf {'e', "."}, 8354622Sbillf {'f', "..-."}, 8454622Sbillf {'g', "--."}, 8554622Sbillf {'h', "...."}, 8654622Sbillf {'i', ".."}, 8754622Sbillf {'j', ".---"}, 8854622Sbillf {'k', "-.-"}, 8954622Sbillf {'l', ".-.."}, 9054622Sbillf {'m', "--"}, 9154622Sbillf {'n', "-."}, 9254622Sbillf {'o', "---"}, 9354622Sbillf {'p', ".--."}, 9454622Sbillf {'q', "--.-"}, 9554622Sbillf {'r', ".-."}, 9654622Sbillf {'s', "..."}, 9754622Sbillf {'t', "-"}, 9854622Sbillf {'u', "..-"}, 9954622Sbillf {'v', "...-"}, 10054622Sbillf {'w', ".--"}, 10154622Sbillf {'x', "-..-"}, 10254622Sbillf {'y', "-.--"}, 10354622Sbillf {'z', "--.."}, 10410352Sjoerg 10510352Sjoerg /* digits */ 10610352Sjoerg 10754622Sbillf {'0', "-----"}, 10854622Sbillf {'1', ".----"}, 10954622Sbillf {'2', "..---"}, 11054622Sbillf {'3', "...--"}, 11154622Sbillf {'4', "....-"}, 11254622Sbillf {'5', "....."}, 11354622Sbillf {'6', "-...."}, 11454622Sbillf {'7', "--..."}, 11554622Sbillf {'8', "---.."}, 11654622Sbillf {'9', "----."}, 11710352Sjoerg 11810352Sjoerg /* punctuation */ 11910352Sjoerg 12054622Sbillf {',', "--..--"}, 12154622Sbillf {'.', ".-.-.-"}, 122126040Sfanf {'"', ".-..-."}, 123126040Sfanf {'!', "..--."}, 12454622Sbillf {'?', "..--.."}, 12554622Sbillf {'/', "-..-."}, 12654622Sbillf {'-', "-....-"}, 12754622Sbillf {'=', "-...-"}, /* BT */ 12854622Sbillf {':', "---..."}, 12954622Sbillf {';', "-.-.-."}, 13054622Sbillf {'(', "-.--."}, /* KN */ 13154622Sbillf {')', "-.--.-"}, 13254622Sbillf {'$', "...-..-"}, 13354622Sbillf {'+', ".-.-."}, /* AR */ 134126044Sfanf {'@', ".--.-."}, /* AC */ 13510352Sjoerg 13610352Sjoerg /* prosigns without already assigned values */ 13710352Sjoerg 13854622Sbillf {'#', ".-..."}, /* AS */ 139126040Sfanf {'&', "...-.-"}, /* SK */ 14054622Sbillf {'*', "...-."}, /* VE */ 14154622Sbillf {'%', "-...-.-"}, /* BK */ 14210352Sjoerg 14354622Sbillf {'\0', ""} 14410352Sjoerg}; 14510352Sjoerg 146235618Sdim/* 147235618Sdim * Code-points for some Latin1 chars in ISO-8859-1 encoding. 148235618Sdim * UTF-8 encoded chars in the comments. 149235618Sdim */ 150129114Sddsstatic const struct morsetab iso8859_1tab[] = { 151235618Sdim {'\340', ".--.-"}, /* �� */ 152235618Sdim {'\341', ".--.-"}, /* �� */ 153235618Sdim {'\342', ".--.-"}, /* �� */ 154235618Sdim {'\344', ".-.-"}, /* �� */ 155235618Sdim {'\347', "-.-.."}, /* �� */ 156235618Sdim {'\350', "..-.."}, /* �� */ 157235618Sdim {'\351', "..-.."}, /* �� */ 158235618Sdim {'\352', "-..-."}, /* �� */ 159235618Sdim {'\366', "---."}, /* �� */ 160235618Sdim {'\374', "..--"}, /* �� */ 16110352Sjoerg 16254622Sbillf {'\0', ""} 16310352Sjoerg}; 16410352Sjoerg 165235618Sdim/* 166235618Sdim * Code-points for some Greek chars in ISO-8859-7 encoding. 167235618Sdim * UTF-8 encoded chars in the comments. 168235618Sdim */ 169129114Sddsstatic const struct morsetab iso8859_7tab[] = { 170129114Sdds /* 171129114Sdds * This table does not implement: 172129114Sdds * - the special sequences for the seven diphthongs, 173129114Sdds * - the punctuation differences. 174129114Sdds * Implementing these features would introduce too many 175129114Sdds * special-cases in the program's main loop. 176221907Suqs * The diphthong sequences are: 177129114Sdds * alpha iota .-.- 178129114Sdds * alpha upsilon ..-- 179129114Sdds * epsilon upsilon ---. 180129114Sdds * eta upsilon ...- 181221907Suqs * omicron iota ---.. 182221907Suqs * omicron upsilon ..- 183129114Sdds * upsilon iota .--- 184129114Sdds * The different punctuation symbols are: 185129114Sdds * ; ..-.- 186129114Sdds * ! --..-- 187129114Sdds */ 188235618Sdim {'\341', ".-"}, /* ��, alpha */ 189235618Sdim {'\334', ".-"}, /* ��, alpha with acute */ 190235618Sdim {'\342', "-..."}, /* ��, beta */ 191235618Sdim {'\343', "--."}, /* ��, gamma */ 192235618Sdim {'\344', "-.."}, /* ��, delta */ 193235618Sdim {'\345', "."}, /* ��, epsilon */ 194235618Sdim {'\335', "."}, /* ��, epsilon with acute */ 195235618Sdim {'\346', "--.."}, /* ��, zeta */ 196235618Sdim {'\347', "...."}, /* ��, eta */ 197235618Sdim {'\336', "...."}, /* ��, eta with acute */ 198235618Sdim {'\350', "-.-."}, /* ��, theta */ 199235618Sdim {'\351', ".."}, /* ��, iota */ 200235618Sdim {'\337', ".."}, /* ��, iota with acute */ 201235618Sdim {'\372', ".."}, /* ��, iota with diaeresis */ 202235618Sdim {'\300', ".."}, /* ��, iota with acute and diaeresis */ 203235618Sdim {'\352', "-.-"}, /* ��, kappa */ 204235618Sdim {'\353', ".-.."}, /* ��, lambda */ 205235618Sdim {'\354', "--"}, /* ��, mu */ 206235618Sdim {'\355', "-."}, /* ��, nu */ 207235618Sdim {'\356', "-..-"}, /* ��, xi */ 208235618Sdim {'\357', "---"}, /* ��, omicron */ 209235618Sdim {'\374', "---"}, /* ��, omicron with acute */ 210235618Sdim {'\360', ".--."}, /* ��, pi */ 211235618Sdim {'\361', ".-."}, /* ��, rho */ 212235618Sdim {'\363', "..."}, /* ��, sigma */ 213235618Sdim {'\362', "..."}, /* ��, final sigma */ 214235618Sdim {'\364', "-"}, /* ��, tau */ 215235618Sdim {'\365', "-.--"}, /* ��, upsilon */ 216235618Sdim {'\375', "-.--"}, /* ��, upsilon with acute */ 217235618Sdim {'\373', "-.--"}, /* ��, upsilon and diaeresis */ 218235618Sdim {'\340', "-.--"}, /* ��, upsilon with acute and diaeresis */ 219235618Sdim {'\366', "..-."}, /* ��, phi */ 220235618Sdim {'\367', "----"}, /* ��, chi */ 221235618Sdim {'\370', "--.-"}, /* ��, psi */ 222235618Sdim {'\371', ".--"}, /* ��, omega */ 223235618Sdim {'\376', ".--"}, /* ��, omega with acute */ 224129114Sdds 225129114Sdds {'\0', ""} 226129114Sdds}; 227129114Sdds 228235618Sdim/* 229235618Sdim * Code-points for the Cyrillic alphabet in KOI8-R encoding. 230235618Sdim * UTF-8 encoded chars in the comments. 231235618Sdim */ 23254622Sbillfstatic const struct morsetab koi8rtab[] = { 233235618Sdim {'\301', ".-"}, /* ��, a */ 234235618Sdim {'\302', "-..."}, /* ��, be */ 235235618Sdim {'\327', ".--"}, /* ��, ve */ 236235618Sdim {'\307', "--."}, /* ��, ge */ 237235618Sdim {'\304', "-.."}, /* ��, de */ 238235618Sdim {'\305', "."}, /* ��, ye */ 239235618Sdim {'\243', "."}, /* ��, yo, the same as ye */ 240235618Sdim {'\326', "...-"}, /* ��, she */ 241235618Sdim {'\332', "--.."}, /* ��, ze */ 242235618Sdim {'\311', ".."}, /* ��, i */ 243235618Sdim {'\312', ".---"}, /* ��, i kratkoye */ 244235618Sdim {'\313', "-.-"}, /* ��, ka */ 245235618Sdim {'\314', ".-.."}, /* ��, el */ 246235618Sdim {'\315', "--"}, /* ��, em */ 247235618Sdim {'\316', "-."}, /* ��, en */ 248235618Sdim {'\317', "---"}, /* ��, o */ 249235618Sdim {'\320', ".--."}, /* ��, pe */ 250235618Sdim {'\322', ".-."}, /* ��, er */ 251235618Sdim {'\323', "..."}, /* ��, es */ 252235618Sdim {'\324', "-"}, /* ��, te */ 253235618Sdim {'\325', "..-"}, /* ��, u */ 254235618Sdim {'\306', "..-."}, /* ��, ef */ 255235618Sdim {'\310', "...."}, /* ��, kha */ 256235618Sdim {'\303', "-.-."}, /* ��, ce */ 257235618Sdim {'\336', "---."}, /* ��, che */ 258235618Sdim {'\333', "----"}, /* ��, sha */ 259235618Sdim {'\335', "--.-"}, /* ��, shcha */ 260235618Sdim {'\331', "-.--"}, /* ��, yi */ 261235618Sdim {'\330', "-..-"}, /* ��, myakhkij znak */ 262235618Sdim {'\334', "..-.."}, /* ��, ae */ 263235618Sdim {'\300', "..--"}, /* ��, yu */ 264235618Sdim {'\321', ".-.-"}, /* ��, ya */ 26510352Sjoerg 26654622Sbillf {'\0', ""} 26710352Sjoerg}; 26810352Sjoerg 269249840Seadlerstatic void show(const char *), play(const char *), morse(char); 270249840Seadlerstatic void ttyout(const char *); 271249840Seadlerstatic void sighandler(int); 27210352Sjoerg 273147110Sjoerg#define GETOPTOPTS "c:d:ef:lsw:" 27457527Sjoerg#define USAGE \ 275147110Sjoerg"usage: morse [-els] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n" 27657527Sjoerg 277249840Seadlerstatic int pflag, lflag, sflag, eflag; 278249840Seadlerstatic int wpm = 20; /* effective words per minute */ 279249840Seadlerstatic int cpm; /* effective words per minute between 280147110Sjoerg * characters */ 28110352Sjoerg#define FREQUENCY 600 282249840Seadlerstatic int freq = FREQUENCY; 28357527Sjoergstatic char *device; /* for tty-controlled generator */ 28410352Sjoerg 28510352Sjoerg#define DASH_LEN 3 28610352Sjoerg#define CHAR_SPACE 3 28710352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1) 288249840Seadlerstatic float dot_clock; 289249840Seadlerstatic float cdot_clock; 290249840Seadlerstatic int spkr, line; 291249840Seadlerstatic struct termios otty, ntty; 292249840Seadlerstatic int olflags; 29357527Sjoerg 29457527Sjoerg#ifdef SPEAKER 295249840Seadlerstatic tone_t sound; 29657527Sjoerg#undef GETOPTOPTS 297147110Sjoerg#define GETOPTOPTS "c:d:ef:lpsw:" 29857527Sjoerg#undef USAGE 29957527Sjoerg#define USAGE \ 300147110Sjoerg"usage: morse [-elps] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n" 30110352Sjoerg#endif 30210352Sjoerg 30378793Sachestatic const struct morsetab *hightab; 30410352Sjoerg 30510352Sjoergint 30610352Sjoergmain(int argc, char **argv) 3072490Sjkh{ 30857527Sjoerg int ch, lflags; 30978793Sache char *p, *codeset; 3102490Sjkh 31157527Sjoerg while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1) 31210352Sjoerg switch ((char) ch) { 313221907Suqs case 'c': 314221907Suqs cpm = atoi(optarg); 315221907Suqs break; 31657527Sjoerg case 'd': 31757527Sjoerg device = optarg; 31857527Sjoerg break; 31957527Sjoerg case 'e': 32057527Sjoerg eflag = 1; 32157527Sjoerg setvbuf(stdout, 0, _IONBF, 0); 32257527Sjoerg break; 32310352Sjoerg case 'f': 32410352Sjoerg freq = atoi(optarg); 32510352Sjoerg break; 326121945Sphk case 'l': 327121945Sphk lflag = 1; 328121945Sphk break; 32957527Sjoerg#ifdef SPEAKER 33010352Sjoerg case 'p': 33110352Sjoerg pflag = 1; 33210352Sjoerg break; 33357527Sjoerg#endif 3342490Sjkh case 's': 3352490Sjkh sflag = 1; 3362490Sjkh break; 33710352Sjoerg case 'w': 33810352Sjoerg wpm = atoi(optarg); 33910352Sjoerg break; 3402490Sjkh case '?': 3412490Sjkh default: 34257527Sjoerg fputs(USAGE, stderr); 3432490Sjkh exit(1); 3442490Sjkh } 345121945Sphk if (sflag && lflag) { 346121945Sphk fputs("morse: only one of -l and -s allowed\n", stderr); 34710352Sjoerg exit(1); 34810352Sjoerg } 349121945Sphk if ((pflag || device) && (sflag || lflag)) { 350121945Sphk fputs("morse: only one of -p, -d and -l, -s allowed\n", stderr); 351121945Sphk exit(1); 352121945Sphk } 353147110Sjoerg if (cpm == 0) 354147110Sjoerg cpm = wpm; 355147110Sjoerg if ((pflag || device) && ((wpm < 1) || (wpm > 60) || (cpm < 1) || (cpm > 60))) { 35610352Sjoerg fputs("morse: insane speed\n", stderr); 35710352Sjoerg exit(1); 35810352Sjoerg } 35957527Sjoerg if ((pflag || device) && (freq == 0)) 36010352Sjoerg freq = FREQUENCY; 36110352Sjoerg 36210352Sjoerg#ifdef SPEAKER 36310352Sjoerg if (pflag) { 36410352Sjoerg if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 36510352Sjoerg perror(SPEAKER); 36610352Sjoerg exit(1); 36710352Sjoerg } 36857527Sjoerg } else 36957527Sjoerg#endif 37057527Sjoerg if (device) { 37157527Sjoerg if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) { 37257527Sjoerg perror("open tty line"); 37357527Sjoerg exit(1); 37457527Sjoerg } 37557527Sjoerg if (tcgetattr(line, &otty) == -1) { 37657527Sjoerg perror("tcgetattr() failed"); 37757527Sjoerg exit(1); 37857527Sjoerg } 37957527Sjoerg ntty = otty; 38057527Sjoerg ntty.c_cflag |= CLOCAL; 38157527Sjoerg tcsetattr(line, TCSANOW, &ntty); 38257527Sjoerg lflags = fcntl(line, F_GETFL); 38357527Sjoerg lflags &= ~O_NONBLOCK; 38457527Sjoerg fcntl(line, F_SETFL, &lflags); 38557527Sjoerg ioctl(line, TIOCMGET, &lflags); 38657527Sjoerg lflags &= ~TIOCM_RTS; 38757527Sjoerg olflags = lflags; 38857527Sjoerg ioctl(line, TIOCMSET, &lflags); 38957527Sjoerg (void)signal(SIGHUP, sighandler); 39057527Sjoerg (void)signal(SIGINT, sighandler); 39157527Sjoerg (void)signal(SIGQUIT, sighandler); 39257527Sjoerg (void)signal(SIGTERM, sighandler); 39357527Sjoerg } 39457527Sjoerg if (pflag || device) { 39510352Sjoerg dot_clock = wpm / 2.4; /* dots/sec */ 39610352Sjoerg dot_clock = 1 / dot_clock; /* duration of a dot */ 39710352Sjoerg dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 39810352Sjoerg /* the dot rate */ 39910352Sjoerg dot_clock = dot_clock * 100; /* scale for ioctl */ 400147110Sjoerg 401147110Sjoerg cdot_clock = cpm / 2.4; /* dots/sec */ 402147110Sjoerg cdot_clock = 1 / cdot_clock; /* duration of a dot */ 403147110Sjoerg cdot_clock = cdot_clock / 2; /* dot_clock runs at twice */ 404147110Sjoerg /* the dot rate */ 405147110Sjoerg cdot_clock = cdot_clock * 100; /* scale for ioctl */ 40610352Sjoerg } 40757527Sjoerg 4082490Sjkh argc -= optind; 4092490Sjkh argv += optind; 4102490Sjkh 41178793Sache if (setlocale(LC_CTYPE, "") != NULL && 41278793Sache *(codeset = nl_langinfo(CODESET)) != '\0') { 41378793Sache if (strcmp(codeset, "KOI8-R") == 0) 41410352Sjoerg hightab = koi8rtab; 41578793Sache else if (strcmp(codeset, "ISO8859-1") == 0 || 41678793Sache strcmp(codeset, "ISO8859-15") == 0) 417129114Sdds hightab = iso8859_1tab; 418129114Sdds else if (strcmp(codeset, "ISO8859-7") == 0) 419129114Sdds hightab = iso8859_7tab; 42010352Sjoerg } 42110352Sjoerg 422121945Sphk if (lflag) 423121945Sphk printf("m"); 42410352Sjoerg if (*argv) { 4252490Sjkh do { 42610352Sjoerg for (p = *argv; *p; ++p) { 42757527Sjoerg if (eflag) 42857527Sjoerg putchar(*p); 42929018Sache morse(*p); 43010352Sjoerg } 43157527Sjoerg if (eflag) 43257527Sjoerg putchar(' '); 43329018Sache morse(' '); 4342490Sjkh } while (*++argv); 43510352Sjoerg } else { 43657527Sjoerg while ((ch = getchar()) != EOF) { 43757527Sjoerg if (eflag) 43857527Sjoerg putchar(ch); 43910352Sjoerg morse(ch); 44057527Sjoerg } 44110352Sjoerg } 44257527Sjoerg if (device) 44357527Sjoerg tcsetattr(line, TCSANOW, &otty); 44410352Sjoerg exit(0); 4452490Sjkh} 4462490Sjkh 447249840Seadlerstatic void 44810352Sjoergmorse(char c) 4492490Sjkh{ 45054622Sbillf const struct morsetab *m; 45110352Sjoerg 45229018Sache if (isalpha((unsigned char)c)) 45329018Sache c = tolower((unsigned char)c); 45410352Sjoerg if ((c == '\r') || (c == '\n')) 45510352Sjoerg c = ' '; 45610352Sjoerg if (c == ' ') { 457121945Sphk if (pflag) 45810352Sjoerg play(" "); 459121945Sphk else if (device) 46057527Sjoerg ttyout(" "); 461121945Sphk else if (lflag) 462121945Sphk printf("\n"); 463121945Sphk else 46410352Sjoerg show(""); 465121945Sphk return; 46610352Sjoerg } 46710352Sjoerg for (m = ((unsigned char)c < 0x80? mtab: hightab); 46878793Sache m != NULL && m->inchar != '\0'; 46910352Sjoerg m++) { 47010352Sjoerg if (m->inchar == c) { 47110352Sjoerg if (pflag) { 47210352Sjoerg play(m->morse); 47357527Sjoerg } else if (device) { 47457527Sjoerg ttyout(m->morse); 47510352Sjoerg } else 47610352Sjoerg show(m->morse); 47710352Sjoerg } 47810352Sjoerg } 4792490Sjkh} 4802490Sjkh 481249840Seadlerstatic void 48210352Sjoergshow(const char *s) 4832490Sjkh{ 484121945Sphk if (lflag) { 485121945Sphk printf("%s ", s); 486121945Sphk } else if (sflag) { 487121945Sphk printf(" %s\n", s); 488121945Sphk } else { 48910352Sjoerg for (; *s; ++s) 490179654Sscf printf(" %s", *s == '.' ? *(s + 1) == '\0' ? "dit" : 491179654Sscf "di" : "dah"); 492121945Sphk printf("\n"); 493121945Sphk } 4942490Sjkh} 49510352Sjoerg 496249840Seadlerstatic void 49710352Sjoergplay(const char *s) 49810352Sjoerg{ 49910352Sjoerg#ifdef SPEAKER 50010352Sjoerg const char *c; 50110352Sjoerg 50210352Sjoerg for (c = s; *c != '\0'; c++) { 50329018Sache switch (*c) { 50410352Sjoerg case '.': 50510352Sjoerg sound.frequency = freq; 50610352Sjoerg sound.duration = dot_clock; 50710352Sjoerg break; 50810352Sjoerg case '-': 50910352Sjoerg sound.frequency = freq; 51010352Sjoerg sound.duration = dot_clock * DASH_LEN; 51110352Sjoerg break; 51210352Sjoerg case ' ': 51310352Sjoerg sound.frequency = 0; 514147110Sjoerg sound.duration = cdot_clock * WORD_SPACE; 51510352Sjoerg break; 51610352Sjoerg default: 51710352Sjoerg sound.duration = 0; 51810352Sjoerg } 51910352Sjoerg if (sound.duration) { 52010352Sjoerg if (ioctl(spkr, SPKRTONE, &sound) == -1) { 52110352Sjoerg perror("ioctl play"); 52210352Sjoerg exit(1); 52310352Sjoerg } 52410352Sjoerg } 52510352Sjoerg sound.frequency = 0; 52610352Sjoerg sound.duration = dot_clock; 52710352Sjoerg if (ioctl(spkr, SPKRTONE, &sound) == -1) { 52810352Sjoerg perror("ioctl rest"); 52910352Sjoerg exit(1); 53010352Sjoerg } 53110352Sjoerg } 53210352Sjoerg sound.frequency = 0; 533147110Sjoerg sound.duration = cdot_clock * CHAR_SPACE; 53410352Sjoerg ioctl(spkr, SPKRTONE, &sound); 53510352Sjoerg#endif 53610352Sjoerg} 53757527Sjoerg 538249840Seadlerstatic void 53957527Sjoergttyout(const char *s) 54057527Sjoerg{ 54157527Sjoerg const char *c; 54257527Sjoerg int duration, on, lflags; 54357527Sjoerg 54457527Sjoerg for (c = s; *c != '\0'; c++) { 54557527Sjoerg switch (*c) { 54657527Sjoerg case '.': 54757527Sjoerg on = 1; 54857527Sjoerg duration = dot_clock; 54957527Sjoerg break; 55057527Sjoerg case '-': 55157527Sjoerg on = 1; 55257527Sjoerg duration = dot_clock * DASH_LEN; 55357527Sjoerg break; 55457527Sjoerg case ' ': 55557527Sjoerg on = 0; 556147110Sjoerg duration = cdot_clock * WORD_SPACE; 55757527Sjoerg break; 55857527Sjoerg default: 55957527Sjoerg on = 0; 56057527Sjoerg duration = 0; 56157527Sjoerg } 56257527Sjoerg if (on) { 56357527Sjoerg ioctl(line, TIOCMGET, &lflags); 56457527Sjoerg lflags |= TIOCM_RTS; 56557527Sjoerg ioctl(line, TIOCMSET, &lflags); 56657527Sjoerg } 56757527Sjoerg duration *= 10000; 56857527Sjoerg if (duration) 56957527Sjoerg usleep(duration); 57057527Sjoerg ioctl(line, TIOCMGET, &lflags); 57157527Sjoerg lflags &= ~TIOCM_RTS; 57257527Sjoerg ioctl(line, TIOCMSET, &lflags); 57357527Sjoerg duration = dot_clock * 10000; 57457527Sjoerg usleep(duration); 57557527Sjoerg } 576147110Sjoerg duration = cdot_clock * CHAR_SPACE * 10000; 57757527Sjoerg usleep(duration); 57857527Sjoerg} 57957527Sjoerg 580249840Seadlerstatic void 58157527Sjoergsighandler(int signo) 58257527Sjoerg{ 58357527Sjoerg 58457527Sjoerg ioctl(line, TIOCMSET, &olflags); 58557527Sjoerg tcsetattr(line, TCSANOW, &otty); 58657527Sjoerg 58757527Sjoerg signal(signo, SIG_DFL); 58857527Sjoerg (void)kill(getpid(), signo); 58957527Sjoerg} 590