morse.c revision 203921
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.
132490Sjkh * 3. All advertising materials mentioning features or use of this software
142490Sjkh *    must display the following acknowledgement:
152490Sjkh *	This product includes software developed by the University of
162490Sjkh *	California, Berkeley and its contributors.
172490Sjkh * 4. Neither the name of the University nor the names of its contributors
182490Sjkh *    may be used to endorse or promote products derived from this software
192490Sjkh *    without specific prior written permission.
202490Sjkh *
212490Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
222490Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232490Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242490Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
252490Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
262490Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
272490Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
282490Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
292490Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
302490Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
312490Sjkh * SUCH DAMAGE.
322490Sjkh */
332490Sjkh
3410352Sjoerg/*
35179654Sscf * Taught to send *real* morse by Lyndon Nerenberg (VE6BBM)
36179654Sscf * <lyndon@orthanc.ca>
3710352Sjoerg */
3810352Sjoerg
392490Sjkh#ifndef lint
4053920Sbillfstatic const char copyright[] =
412490Sjkh"@(#) Copyright (c) 1988, 1993\n\
422490Sjkh	The Regents of the University of California.  All rights reserved.\n";
432490Sjkh#endif /* not lint */
442490Sjkh
452490Sjkh#ifndef lint
4653920Sbillf#if 0
472490Sjkhstatic char sccsid[] = "@(#)morse.c	8.1 (Berkeley) 5/31/93";
4853920Sbillf#endif
4953920Sbillfstatic const char rcsid[] =
5053920Sbillf "$FreeBSD: head/games/morse/morse.c 203921 2010-02-15 14:31:05Z uqs $";
512490Sjkh#endif /* not lint */
522490Sjkh
5357527Sjoerg#include <sys/time.h>
5457527Sjoerg
552490Sjkh#include <ctype.h>
5657527Sjoerg#include <fcntl.h>
5778793Sache#include <langinfo.h>
5810352Sjoerg#include <locale.h>
5957527Sjoerg#include <signal.h>
6057527Sjoerg#include <stdio.h>
6110352Sjoerg#include <stdlib.h>
6235857Sjb#include <string.h>
6357527Sjoerg#include <termios.h>
6454622Sbillf#include <unistd.h>
652490Sjkh
66203479Simp/* Always use the speaker, let the open fail if -p is selected */
67203479Simp#define SPEAKER "/dev/speaker"
68203479Simp
6910352Sjoerg#ifdef SPEAKER
70152306Sru#include <dev/speaker/speaker.h>
7110352Sjoerg#endif
7210352Sjoerg
7310352Sjoergstruct morsetab {
74203921Suqs	const char      inchar;
75203921Suqs	const char     *morse;
762490Sjkh};
772490Sjkh
7854622Sbillfstatic const struct morsetab mtab[] = {
792490Sjkh
8010352Sjoerg	/* letters */
8110352Sjoerg
8254622Sbillf	{'a', ".-"},
8354622Sbillf	{'b', "-..."},
8454622Sbillf	{'c', "-.-."},
8554622Sbillf	{'d', "-.."},
8654622Sbillf	{'e', "."},
8754622Sbillf	{'f', "..-."},
8854622Sbillf	{'g', "--."},
8954622Sbillf	{'h', "...."},
9054622Sbillf	{'i', ".."},
9154622Sbillf	{'j', ".---"},
9254622Sbillf	{'k', "-.-"},
9354622Sbillf	{'l', ".-.."},
9454622Sbillf	{'m', "--"},
9554622Sbillf	{'n', "-."},
9654622Sbillf	{'o', "---"},
9754622Sbillf	{'p', ".--."},
9854622Sbillf	{'q', "--.-"},
9954622Sbillf	{'r', ".-."},
10054622Sbillf	{'s', "..."},
10154622Sbillf	{'t', "-"},
10254622Sbillf	{'u', "..-"},
10354622Sbillf	{'v', "...-"},
10454622Sbillf	{'w', ".--"},
10554622Sbillf	{'x', "-..-"},
10654622Sbillf	{'y', "-.--"},
10754622Sbillf	{'z', "--.."},
10810352Sjoerg
10910352Sjoerg	/* digits */
11010352Sjoerg
11154622Sbillf	{'0', "-----"},
11254622Sbillf	{'1', ".----"},
11354622Sbillf	{'2', "..---"},
11454622Sbillf	{'3', "...--"},
11554622Sbillf	{'4', "....-"},
11654622Sbillf	{'5', "....."},
11754622Sbillf	{'6', "-...."},
11854622Sbillf	{'7', "--..."},
11954622Sbillf	{'8', "---.."},
12054622Sbillf	{'9', "----."},
12110352Sjoerg
12210352Sjoerg	/* punctuation */
12310352Sjoerg
12454622Sbillf	{',', "--..--"},
12554622Sbillf	{'.', ".-.-.-"},
126126040Sfanf	{'"', ".-..-."},
127126040Sfanf	{'!', "..--."},
12854622Sbillf	{'?', "..--.."},
12954622Sbillf	{'/', "-..-."},
13054622Sbillf	{'-', "-....-"},
13154622Sbillf	{'=', "-...-"},		/* BT */
13254622Sbillf	{':', "---..."},
13354622Sbillf	{';', "-.-.-."},
13454622Sbillf	{'(', "-.--."},		/* KN */
13554622Sbillf	{')', "-.--.-"},
13654622Sbillf	{'$', "...-..-"},
13754622Sbillf	{'+', ".-.-."},		/* AR */
138126044Sfanf	{'@', ".--.-."},	/* AC */
13910352Sjoerg
14010352Sjoerg	/* prosigns without already assigned values */
14110352Sjoerg
14254622Sbillf	{'#', ".-..."},		/* AS */
143126040Sfanf	{'&', "...-.-"},	/* SK */
14454622Sbillf	{'*', "...-."},		/* VE */
14554622Sbillf	{'%', "-...-.-"},	/* BK */
14610352Sjoerg
14754622Sbillf	{'\0', ""}
14810352Sjoerg};
14910352Sjoerg
15010352Sjoerg
151129114Sddsstatic const struct morsetab iso8859_1tab[] = {
15254622Sbillf	{'�', ".--.-"},
15354622Sbillf	{'�', ".--.-"},
15454622Sbillf	{'�', ".--.-"},
15554622Sbillf	{'�', ".-.-"},
15654622Sbillf	{'�', "-.-.."},
15754622Sbillf	{'�', "..-.."},
15854622Sbillf	{'�', "..-.."},
15954622Sbillf	{'�', "-..-."},
16054622Sbillf	{'�', "---."},
16154622Sbillf	{'�', "..--"},
16210352Sjoerg
16354622Sbillf	{'\0', ""}
16410352Sjoerg};
16510352Sjoerg
166129114Sddsstatic const struct morsetab iso8859_7tab[] = {
167129114Sdds	/*
168129114Sdds	 * The greek alphabet; you'll need an 8859-7 font in order
169129114Sdds	 * to see the actual characters.
170129114Sdds	 * This table does not implement:
171129114Sdds	 * - the special sequences for the seven diphthongs,
172129114Sdds	 * - the punctuation differences.
173129114Sdds	 * Implementing these features would introduce too many
174129114Sdds	 * special-cases in the program's main loop.
175129114Sdds	 * The diphtong sequences are:
176129114Sdds	 * alpha iota		.-.-
177129114Sdds	 * alpha upsilon	..--
178129114Sdds	 * epsilon upsilon	---.
179129114Sdds	 * eta upsilon		...-
180129114Sdds	 * omikron iota		---..
181129114Sdds	 * omikron upsilon	..-
182129114Sdds	 * upsilon iota		.---
183129114Sdds	 * The different punctuation symbols are:
184129114Sdds	 * ;	..-.-
185129114Sdds	 * !	--..--
186129114Sdds	 */
187129114Sdds	{'�', ".-"},	/* alpha */
188129114Sdds	{'�', ".-"},	/* alpha with acute */
189129114Sdds	{'�', "-..."},	/* beta */
190129114Sdds	{'�', "--."},	/* gamma */
191129114Sdds	{'�', "-.."},	/* delta */
192129114Sdds	{'�', "."},	/* epsilon */
193129114Sdds	{'�', "."},	/* epsilon with acute */
194129114Sdds	{'�', "--.."},	/* zeta */
195129114Sdds	{'�', "...."},	/* eta */
196129114Sdds	{'�', "...."},	/* eta with acute */
197129114Sdds	{'�', "-.-."},	/* theta */
198129114Sdds	{'�', ".."},	/* iota */
199129114Sdds	{'�', ".."},	/* iota with acute */
200129114Sdds	{'�', ".."},	/* iota with diairesis */
201129114Sdds	{'�', ".."},	/* iota with acute and diairesis */
202129114Sdds	{'�', "-.-"},	/* kappa */
203129114Sdds	{'�', ".-.."},	/* lamda */
204129114Sdds	{'�', "--"},	/* mu */
205129114Sdds	{'�', "-."},	/* nu */
206129114Sdds	{'�', "-..-"},	/* xi */
207129114Sdds	{'�', "---"},	/* omicron */
208129114Sdds	{'�', "---"},	/* omicron with acute */
209129114Sdds	{'�', ".--."},	/* pi */
210129114Sdds	{'�', ".-."},	/* rho */
211129114Sdds	{'�', "..."},	/* sigma */
212129114Sdds	{'�', "..."},	/* final sigma */
213129114Sdds	{'�', "-"},	/* tau */
214129114Sdds	{'�', "-.--"},	/* upsilon */
215129114Sdds	{'�', "-.--"},	/* upsilon with acute */
216129114Sdds	{'�', "-.--"},	/* upsilon and diairesis */
217129114Sdds	{'�', "-.--"},	/* upsilon with acute and diairesis */
218129114Sdds	{'�', "..-."},	/* phi */
219129114Sdds	{'�', "----"},	/* chi */
220129114Sdds	{'�', "--.-"},	/* psi */
221129114Sdds	{'�', ".--"},	/* omega */
222129114Sdds	{'�', ".--"},	/* omega with acute */
223129114Sdds
224129114Sdds	{'\0', ""}
225129114Sdds};
226129114Sdds
22754622Sbillfstatic const struct morsetab koi8rtab[] = {
22810352Sjoerg	/*
22910352Sjoerg	 * the cyrillic alphabet; you'll need a KOI8R font in order
23010352Sjoerg	 * to see the actual characters
23110352Sjoerg	 */
23254622Sbillf	{'�', ".-"},		/* a */
23354622Sbillf	{'�', "-..."},	/* be */
23454622Sbillf	{'�', ".--"},	/* ve */
23554622Sbillf	{'�', "--."},	/* ge */
23654622Sbillf	{'�', "-.."},	/* de */
23754622Sbillf	{'�', "."},		/* ye */
23854622Sbillf	{'�', "."},         	/* yo, the same as ye */
23954622Sbillf	{'�', "...-"},	/* she */
24054622Sbillf	{'�', "--.."},	/* ze */
24154622Sbillf	{'�', ".."},		/* i */
24254622Sbillf	{'�', ".---"},	/* i kratkoye */
24354622Sbillf	{'�', "-.-"},	/* ka */
24454622Sbillf	{'�', ".-.."},	/* el */
24554622Sbillf	{'�', "--"},		/* em */
24654622Sbillf	{'�', "-."},		/* en */
24754622Sbillf	{'�', "---"},	/* o */
24854622Sbillf	{'�', ".--."},	/* pe */
24954622Sbillf	{'�', ".-."},	/* er */
25054622Sbillf	{'�', "..."},	/* es */
25154622Sbillf	{'�', "-"},		/* te */
25254622Sbillf	{'�', "..-"},	/* u */
25354622Sbillf	{'�', "..-."},	/* ef */
25454622Sbillf	{'�', "...."},	/* kha */
25554622Sbillf	{'�', "-.-."},	/* ce */
25654622Sbillf	{'�', "---."},	/* che */
25754622Sbillf	{'�', "----"},	/* sha */
25854622Sbillf	{'�', "--.-"},	/* shcha */
25954622Sbillf	{'�', "-.--"},	/* yi */
26054622Sbillf	{'�', "-..-"},	/* myakhkij znak */
26154622Sbillf	{'�', "..-.."},	/* ae */
26254622Sbillf	{'�', "..--"},	/* yu */
26354622Sbillf	{'�', ".-.-"},	/* ya */
26410352Sjoerg
26554622Sbillf	{'\0', ""}
26610352Sjoerg};
26710352Sjoerg
26810352Sjoergvoid            show(const char *), play(const char *), morse(char);
26957527Sjoergvoid		ttyout(const char *);
27057527Sjoergvoid		sighandler(int);
27110352Sjoerg
272147110Sjoerg#define GETOPTOPTS "c:d:ef:lsw:"
27357527Sjoerg#define USAGE \
274147110Sjoerg"usage: morse [-els] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
27557527Sjoerg
276121945Sphkstatic int      pflag, lflag, sflag, eflag;
277147110Sjoergstatic int      wpm = 20;	/* effective words per minute */
278147110Sjoergstatic int      cpm;		/* effective words per minute between
279147110Sjoerg				 * characters */
28010352Sjoerg#define FREQUENCY 600
28110352Sjoergstatic int      freq = FREQUENCY;
28257527Sjoergstatic char	*device;	/* for tty-controlled generator */
28310352Sjoerg
28410352Sjoerg#define DASH_LEN 3
28510352Sjoerg#define CHAR_SPACE 3
28610352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1)
28710352Sjoergstatic float    dot_clock;
288147110Sjoergstatic float    cdot_clock;
28957527Sjoergint             spkr, line;
29057527Sjoergstruct termios	otty, ntty;
29157527Sjoergint		olflags;
29257527Sjoerg
29357527Sjoerg#ifdef SPEAKER
29410352Sjoergtone_t          sound;
29557527Sjoerg#undef GETOPTOPTS
296147110Sjoerg#define GETOPTOPTS "c:d:ef:lpsw:"
29757527Sjoerg#undef USAGE
29857527Sjoerg#define USAGE \
299147110Sjoerg"usage: morse [-elps] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
30010352Sjoerg#endif
30110352Sjoerg
30278793Sachestatic const struct morsetab *hightab;
30310352Sjoerg
30410352Sjoergint
30510352Sjoergmain(int argc, char **argv)
3062490Sjkh{
30757527Sjoerg	int    ch, lflags;
30878793Sache	char  *p, *codeset;
3092490Sjkh
31057527Sjoerg	while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1)
31110352Sjoerg		switch ((char) ch) {
312147110Sjoerg 		case 'c':
313147110Sjoerg 			cpm = atoi(optarg);
314147110Sjoerg 			break;
31557527Sjoerg		case 'd':
31657527Sjoerg			device = optarg;
31757527Sjoerg			break;
31857527Sjoerg		case 'e':
31957527Sjoerg			eflag = 1;
32057527Sjoerg			setvbuf(stdout, 0, _IONBF, 0);
32157527Sjoerg			break;
32210352Sjoerg		case 'f':
32310352Sjoerg			freq = atoi(optarg);
32410352Sjoerg			break;
325121945Sphk		case 'l':
326121945Sphk			lflag = 1;
327121945Sphk			break;
32857527Sjoerg#ifdef SPEAKER
32910352Sjoerg		case 'p':
33010352Sjoerg			pflag = 1;
33110352Sjoerg			break;
33257527Sjoerg#endif
3332490Sjkh		case 's':
3342490Sjkh			sflag = 1;
3352490Sjkh			break;
33610352Sjoerg		case 'w':
33710352Sjoerg			wpm = atoi(optarg);
33810352Sjoerg			break;
3392490Sjkh		case '?':
3402490Sjkh		default:
34157527Sjoerg			fputs(USAGE, stderr);
3422490Sjkh			exit(1);
3432490Sjkh		}
344121945Sphk	if (sflag && lflag) {
345121945Sphk		fputs("morse: only one of -l and -s allowed\n", stderr);
34610352Sjoerg		exit(1);
34710352Sjoerg	}
348121945Sphk	if ((pflag || device) && (sflag || lflag)) {
349121945Sphk		fputs("morse: only one of -p, -d and -l, -s allowed\n", stderr);
350121945Sphk		exit(1);
351121945Sphk	}
352147110Sjoerg	if (cpm == 0)
353147110Sjoerg		cpm = wpm;
354147110Sjoerg	if ((pflag || device) && ((wpm < 1) || (wpm > 60) || (cpm < 1) || (cpm > 60))) {
35510352Sjoerg		fputs("morse: insane speed\n", stderr);
35610352Sjoerg		exit(1);
35710352Sjoerg	}
35857527Sjoerg	if ((pflag || device) && (freq == 0))
35910352Sjoerg		freq = FREQUENCY;
36010352Sjoerg
36110352Sjoerg#ifdef SPEAKER
36210352Sjoerg	if (pflag) {
36310352Sjoerg		if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
36410352Sjoerg			perror(SPEAKER);
36510352Sjoerg			exit(1);
36610352Sjoerg		}
36757527Sjoerg	} else
36857527Sjoerg#endif
36957527Sjoerg	if (device) {
37057527Sjoerg		if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) {
37157527Sjoerg			perror("open tty line");
37257527Sjoerg			exit(1);
37357527Sjoerg		}
37457527Sjoerg		if (tcgetattr(line, &otty) == -1) {
37557527Sjoerg			perror("tcgetattr() failed");
37657527Sjoerg			exit(1);
37757527Sjoerg		}
37857527Sjoerg		ntty = otty;
37957527Sjoerg		ntty.c_cflag |= CLOCAL;
38057527Sjoerg		tcsetattr(line, TCSANOW, &ntty);
38157527Sjoerg		lflags = fcntl(line, F_GETFL);
38257527Sjoerg		lflags &= ~O_NONBLOCK;
38357527Sjoerg		fcntl(line, F_SETFL, &lflags);
38457527Sjoerg		ioctl(line, TIOCMGET, &lflags);
38557527Sjoerg		lflags &= ~TIOCM_RTS;
38657527Sjoerg		olflags = lflags;
38757527Sjoerg		ioctl(line, TIOCMSET, &lflags);
38857527Sjoerg		(void)signal(SIGHUP, sighandler);
38957527Sjoerg		(void)signal(SIGINT, sighandler);
39057527Sjoerg		(void)signal(SIGQUIT, sighandler);
39157527Sjoerg		(void)signal(SIGTERM, sighandler);
39257527Sjoerg	}
39357527Sjoerg	if (pflag || device) {
39410352Sjoerg		dot_clock = wpm / 2.4;		/* dots/sec */
39510352Sjoerg		dot_clock = 1 / dot_clock;	/* duration of a dot */
39610352Sjoerg		dot_clock = dot_clock / 2;	/* dot_clock runs at twice */
39710352Sjoerg						/* the dot rate */
39810352Sjoerg		dot_clock = dot_clock * 100;	/* scale for ioctl */
399147110Sjoerg
400147110Sjoerg		cdot_clock = cpm / 2.4;		/* dots/sec */
401147110Sjoerg		cdot_clock = 1 / cdot_clock;	/* duration of a dot */
402147110Sjoerg		cdot_clock = cdot_clock / 2;	/* dot_clock runs at twice */
403147110Sjoerg						/* the dot rate */
404147110Sjoerg		cdot_clock = cdot_clock * 100;	/* scale for ioctl */
40510352Sjoerg	}
40657527Sjoerg
4072490Sjkh	argc -= optind;
4082490Sjkh	argv += optind;
4092490Sjkh
41078793Sache	if (setlocale(LC_CTYPE, "") != NULL &&
41178793Sache	    *(codeset = nl_langinfo(CODESET)) != '\0') {
41278793Sache		if (strcmp(codeset, "KOI8-R") == 0)
41310352Sjoerg			hightab = koi8rtab;
41478793Sache		else if (strcmp(codeset, "ISO8859-1") == 0 ||
41578793Sache			 strcmp(codeset, "ISO8859-15") == 0)
416129114Sdds			hightab = iso8859_1tab;
417129114Sdds		else if (strcmp(codeset, "ISO8859-7") == 0)
418129114Sdds			hightab = iso8859_7tab;
41910352Sjoerg	}
42010352Sjoerg
421121945Sphk	if (lflag)
422121945Sphk		printf("m");
42310352Sjoerg	if (*argv) {
4242490Sjkh		do {
42510352Sjoerg			for (p = *argv; *p; ++p) {
42657527Sjoerg				if (eflag)
42757527Sjoerg					putchar(*p);
42829018Sache				morse(*p);
42910352Sjoerg			}
43057527Sjoerg			if (eflag)
43157527Sjoerg				putchar(' ');
43229018Sache			morse(' ');
4332490Sjkh		} while (*++argv);
43410352Sjoerg	} else {
43557527Sjoerg		while ((ch = getchar()) != EOF) {
43657527Sjoerg			if (eflag)
43757527Sjoerg				putchar(ch);
43810352Sjoerg			morse(ch);
43957527Sjoerg		}
44010352Sjoerg	}
44157527Sjoerg	if (device)
44257527Sjoerg		tcsetattr(line, TCSANOW, &otty);
44310352Sjoerg	exit(0);
4442490Sjkh}
4452490Sjkh
44610352Sjoergvoid
44710352Sjoergmorse(char c)
4482490Sjkh{
44954622Sbillf	const struct morsetab *m;
45010352Sjoerg
45129018Sache	if (isalpha((unsigned char)c))
45229018Sache		c = tolower((unsigned char)c);
45310352Sjoerg	if ((c == '\r') || (c == '\n'))
45410352Sjoerg		c = ' ';
45510352Sjoerg	if (c == ' ') {
456121945Sphk		if (pflag)
45710352Sjoerg			play(" ");
458121945Sphk		else if (device)
45957527Sjoerg			ttyout(" ");
460121945Sphk		else if (lflag)
461121945Sphk			printf("\n");
462121945Sphk		else
46310352Sjoerg			show("");
464121945Sphk		return;
46510352Sjoerg	}
46610352Sjoerg	for (m = ((unsigned char)c < 0x80? mtab: hightab);
46778793Sache	     m != NULL && m->inchar != '\0';
46810352Sjoerg	     m++) {
46910352Sjoerg		if (m->inchar == c) {
47010352Sjoerg			if (pflag) {
47110352Sjoerg				play(m->morse);
47257527Sjoerg			} else if (device) {
47357527Sjoerg				ttyout(m->morse);
47410352Sjoerg			} else
47510352Sjoerg				show(m->morse);
47610352Sjoerg		}
47710352Sjoerg	}
4782490Sjkh}
4792490Sjkh
48010352Sjoergvoid
48110352Sjoergshow(const char *s)
4822490Sjkh{
483121945Sphk	if (lflag) {
484121945Sphk		printf("%s ", s);
485121945Sphk	} else if (sflag) {
486121945Sphk		printf(" %s\n", s);
487121945Sphk	} else {
48810352Sjoerg		for (; *s; ++s)
489179654Sscf			printf(" %s", *s == '.' ? *(s + 1) == '\0' ? "dit" :
490179654Sscf			    "di" : "dah");
491121945Sphk		printf("\n");
492121945Sphk	}
4932490Sjkh}
49410352Sjoerg
49510352Sjoergvoid
49610352Sjoergplay(const char *s)
49710352Sjoerg{
49810352Sjoerg#ifdef SPEAKER
49910352Sjoerg	const char *c;
50010352Sjoerg
50110352Sjoerg	for (c = s; *c != '\0'; c++) {
50229018Sache		switch (*c) {
50310352Sjoerg		case '.':
50410352Sjoerg			sound.frequency = freq;
50510352Sjoerg			sound.duration = dot_clock;
50610352Sjoerg			break;
50710352Sjoerg		case '-':
50810352Sjoerg			sound.frequency = freq;
50910352Sjoerg			sound.duration = dot_clock * DASH_LEN;
51010352Sjoerg			break;
51110352Sjoerg		case ' ':
51210352Sjoerg			sound.frequency = 0;
513147110Sjoerg			sound.duration = cdot_clock * WORD_SPACE;
51410352Sjoerg			break;
51510352Sjoerg		default:
51610352Sjoerg			sound.duration = 0;
51710352Sjoerg		}
51810352Sjoerg		if (sound.duration) {
51910352Sjoerg			if (ioctl(spkr, SPKRTONE, &sound) == -1) {
52010352Sjoerg				perror("ioctl play");
52110352Sjoerg				exit(1);
52210352Sjoerg			}
52310352Sjoerg		}
52410352Sjoerg		sound.frequency = 0;
52510352Sjoerg		sound.duration = dot_clock;
52610352Sjoerg		if (ioctl(spkr, SPKRTONE, &sound) == -1) {
52710352Sjoerg			perror("ioctl rest");
52810352Sjoerg			exit(1);
52910352Sjoerg		}
53010352Sjoerg	}
53110352Sjoerg	sound.frequency = 0;
532147110Sjoerg	sound.duration = cdot_clock * CHAR_SPACE;
53310352Sjoerg	ioctl(spkr, SPKRTONE, &sound);
53410352Sjoerg#endif
53510352Sjoerg}
53657527Sjoerg
53757527Sjoergvoid
53857527Sjoergttyout(const char *s)
53957527Sjoerg{
54057527Sjoerg	const char *c;
54157527Sjoerg	int duration, on, lflags;
54257527Sjoerg
54357527Sjoerg	for (c = s; *c != '\0'; c++) {
54457527Sjoerg		switch (*c) {
54557527Sjoerg		case '.':
54657527Sjoerg			on = 1;
54757527Sjoerg			duration = dot_clock;
54857527Sjoerg			break;
54957527Sjoerg		case '-':
55057527Sjoerg			on = 1;
55157527Sjoerg			duration = dot_clock * DASH_LEN;
55257527Sjoerg			break;
55357527Sjoerg		case ' ':
55457527Sjoerg			on = 0;
555147110Sjoerg			duration = cdot_clock * WORD_SPACE;
55657527Sjoerg			break;
55757527Sjoerg		default:
55857527Sjoerg			on = 0;
55957527Sjoerg			duration = 0;
56057527Sjoerg		}
56157527Sjoerg		if (on) {
56257527Sjoerg			ioctl(line, TIOCMGET, &lflags);
56357527Sjoerg			lflags |= TIOCM_RTS;
56457527Sjoerg			ioctl(line, TIOCMSET, &lflags);
56557527Sjoerg		}
56657527Sjoerg		duration *= 10000;
56757527Sjoerg		if (duration)
56857527Sjoerg			usleep(duration);
56957527Sjoerg		ioctl(line, TIOCMGET, &lflags);
57057527Sjoerg		lflags &= ~TIOCM_RTS;
57157527Sjoerg		ioctl(line, TIOCMSET, &lflags);
57257527Sjoerg		duration = dot_clock * 10000;
57357527Sjoerg		usleep(duration);
57457527Sjoerg	}
575147110Sjoerg	duration = cdot_clock * CHAR_SPACE * 10000;
57657527Sjoerg	usleep(duration);
57757527Sjoerg}
57857527Sjoerg
57957527Sjoergvoid
58057527Sjoergsighandler(int signo)
58157527Sjoerg{
58257527Sjoerg
58357527Sjoerg	ioctl(line, TIOCMSET, &olflags);
58457527Sjoerg	tcsetattr(line, TCSANOW, &otty);
58557527Sjoerg
58657527Sjoerg	signal(signo, SIG_DFL);
58757527Sjoerg	(void)kill(getpid(), signo);
58857527Sjoerg}
589