morse.c revision 147110
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/*
3510352Sjoerg * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
3610352Sjoerg * <lyndon@orthanc.com>
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 147110 2005-06-07 19:01:41Z joerg $";
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
6610352Sjoerg#ifdef SPEAKER
6710352Sjoerg#include <machine/speaker.h>
6810352Sjoerg#endif
6910352Sjoerg
7010352Sjoergstruct morsetab {
7110352Sjoerg	char            inchar;
7210352Sjoerg	char           *morse;
732490Sjkh};
742490Sjkh
7554622Sbillfstatic const struct morsetab mtab[] = {
762490Sjkh
7710352Sjoerg	/* letters */
7810352Sjoerg
7954622Sbillf	{'a', ".-"},
8054622Sbillf	{'b', "-..."},
8154622Sbillf	{'c', "-.-."},
8254622Sbillf	{'d', "-.."},
8354622Sbillf	{'e', "."},
8454622Sbillf	{'f', "..-."},
8554622Sbillf	{'g', "--."},
8654622Sbillf	{'h', "...."},
8754622Sbillf	{'i', ".."},
8854622Sbillf	{'j', ".---"},
8954622Sbillf	{'k', "-.-"},
9054622Sbillf	{'l', ".-.."},
9154622Sbillf	{'m', "--"},
9254622Sbillf	{'n', "-."},
9354622Sbillf	{'o', "---"},
9454622Sbillf	{'p', ".--."},
9554622Sbillf	{'q', "--.-"},
9654622Sbillf	{'r', ".-."},
9754622Sbillf	{'s', "..."},
9854622Sbillf	{'t', "-"},
9954622Sbillf	{'u', "..-"},
10054622Sbillf	{'v', "...-"},
10154622Sbillf	{'w', ".--"},
10254622Sbillf	{'x', "-..-"},
10354622Sbillf	{'y', "-.--"},
10454622Sbillf	{'z', "--.."},
10510352Sjoerg
10610352Sjoerg	/* digits */
10710352Sjoerg
10854622Sbillf	{'0', "-----"},
10954622Sbillf	{'1', ".----"},
11054622Sbillf	{'2', "..---"},
11154622Sbillf	{'3', "...--"},
11254622Sbillf	{'4', "....-"},
11354622Sbillf	{'5', "....."},
11454622Sbillf	{'6', "-...."},
11554622Sbillf	{'7', "--..."},
11654622Sbillf	{'8', "---.."},
11754622Sbillf	{'9', "----."},
11810352Sjoerg
11910352Sjoerg	/* punctuation */
12010352Sjoerg
12154622Sbillf	{',', "--..--"},
12254622Sbillf	{'.', ".-.-.-"},
123126040Sfanf	{'"', ".-..-."},
124126040Sfanf	{'!', "..--."},
12554622Sbillf	{'?', "..--.."},
12654622Sbillf	{'/', "-..-."},
12754622Sbillf	{'-', "-....-"},
12854622Sbillf	{'=', "-...-"},		/* BT */
12954622Sbillf	{':', "---..."},
13054622Sbillf	{';', "-.-.-."},
13154622Sbillf	{'(', "-.--."},		/* KN */
13254622Sbillf	{')', "-.--.-"},
13354622Sbillf	{'$', "...-..-"},
13454622Sbillf	{'+', ".-.-."},		/* AR */
135126044Sfanf	{'@', ".--.-."},	/* AC */
13610352Sjoerg
13710352Sjoerg	/* prosigns without already assigned values */
13810352Sjoerg
13954622Sbillf	{'#', ".-..."},		/* AS */
140126040Sfanf	{'&', "...-.-"},	/* SK */
14154622Sbillf	{'*', "...-."},		/* VE */
14254622Sbillf	{'%', "-...-.-"},	/* BK */
14310352Sjoerg
14454622Sbillf	{'\0', ""}
14510352Sjoerg};
14610352Sjoerg
14710352Sjoerg
148129114Sddsstatic const struct morsetab iso8859_1tab[] = {
14954622Sbillf	{'�', ".--.-"},
15054622Sbillf	{'�', ".--.-"},
15154622Sbillf	{'�', ".--.-"},
15254622Sbillf	{'�', ".-.-"},
15354622Sbillf	{'�', "-.-.."},
15454622Sbillf	{'�', "..-.."},
15554622Sbillf	{'�', "..-.."},
15654622Sbillf	{'�', "-..-."},
15754622Sbillf	{'�', "---."},
15854622Sbillf	{'�', "..--"},
15910352Sjoerg
16054622Sbillf	{'\0', ""}
16110352Sjoerg};
16210352Sjoerg
163129114Sddsstatic const struct morsetab iso8859_7tab[] = {
164129114Sdds	/*
165129114Sdds	 * The greek alphabet; you'll need an 8859-7 font in order
166129114Sdds	 * to see the actual characters.
167129114Sdds	 * This table does not implement:
168129114Sdds	 * - the special sequences for the seven diphthongs,
169129114Sdds	 * - the punctuation differences.
170129114Sdds	 * Implementing these features would introduce too many
171129114Sdds	 * special-cases in the program's main loop.
172129114Sdds	 * The diphtong sequences are:
173129114Sdds	 * alpha iota		.-.-
174129114Sdds	 * alpha upsilon	..--
175129114Sdds	 * epsilon upsilon	---.
176129114Sdds	 * eta upsilon		...-
177129114Sdds	 * omikron iota		---..
178129114Sdds	 * omikron upsilon	..-
179129114Sdds	 * upsilon iota		.---
180129114Sdds	 * The different punctuation symbols are:
181129114Sdds	 * ;	..-.-
182129114Sdds	 * !	--..--
183129114Sdds	 */
184129114Sdds	{'�', ".-"},	/* alpha */
185129114Sdds	{'�', ".-"},	/* alpha with acute */
186129114Sdds	{'�', "-..."},	/* beta */
187129114Sdds	{'�', "--."},	/* gamma */
188129114Sdds	{'�', "-.."},	/* delta */
189129114Sdds	{'�', "."},	/* epsilon */
190129114Sdds	{'�', "."},	/* epsilon with acute */
191129114Sdds	{'�', "--.."},	/* zeta */
192129114Sdds	{'�', "...."},	/* eta */
193129114Sdds	{'�', "...."},	/* eta with acute */
194129114Sdds	{'�', "-.-."},	/* theta */
195129114Sdds	{'�', ".."},	/* iota */
196129114Sdds	{'�', ".."},	/* iota with acute */
197129114Sdds	{'�', ".."},	/* iota with diairesis */
198129114Sdds	{'�', ".."},	/* iota with acute and diairesis */
199129114Sdds	{'�', "-.-"},	/* kappa */
200129114Sdds	{'�', ".-.."},	/* lamda */
201129114Sdds	{'�', "--"},	/* mu */
202129114Sdds	{'�', "-."},	/* nu */
203129114Sdds	{'�', "-..-"},	/* xi */
204129114Sdds	{'�', "---"},	/* omicron */
205129114Sdds	{'�', "---"},	/* omicron with acute */
206129114Sdds	{'�', ".--."},	/* pi */
207129114Sdds	{'�', ".-."},	/* rho */
208129114Sdds	{'�', "..."},	/* sigma */
209129114Sdds	{'�', "..."},	/* final sigma */
210129114Sdds	{'�', "-"},	/* tau */
211129114Sdds	{'�', "-.--"},	/* upsilon */
212129114Sdds	{'�', "-.--"},	/* upsilon with acute */
213129114Sdds	{'�', "-.--"},	/* upsilon and diairesis */
214129114Sdds	{'�', "-.--"},	/* upsilon with acute and diairesis */
215129114Sdds	{'�', "..-."},	/* phi */
216129114Sdds	{'�', "----"},	/* chi */
217129114Sdds	{'�', "--.-"},	/* psi */
218129114Sdds	{'�', ".--"},	/* omega */
219129114Sdds	{'�', ".--"},	/* omega with acute */
220129114Sdds
221129114Sdds	{'\0', ""}
222129114Sdds};
223129114Sdds
22454622Sbillfstatic const struct morsetab koi8rtab[] = {
22510352Sjoerg	/*
22610352Sjoerg	 * the cyrillic alphabet; you'll need a KOI8R font in order
22710352Sjoerg	 * to see the actual characters
22810352Sjoerg	 */
22954622Sbillf	{'�', ".-"},		/* a */
23054622Sbillf	{'�', "-..."},	/* be */
23154622Sbillf	{'�', ".--"},	/* ve */
23254622Sbillf	{'�', "--."},	/* ge */
23354622Sbillf	{'�', "-.."},	/* de */
23454622Sbillf	{'�', "."},		/* ye */
23554622Sbillf	{'�', "."},         	/* yo, the same as ye */
23654622Sbillf	{'�', "...-"},	/* she */
23754622Sbillf	{'�', "--.."},	/* ze */
23854622Sbillf	{'�', ".."},		/* i */
23954622Sbillf	{'�', ".---"},	/* i kratkoye */
24054622Sbillf	{'�', "-.-"},	/* ka */
24154622Sbillf	{'�', ".-.."},	/* el */
24254622Sbillf	{'�', "--"},		/* em */
24354622Sbillf	{'�', "-."},		/* en */
24454622Sbillf	{'�', "---"},	/* o */
24554622Sbillf	{'�', ".--."},	/* pe */
24654622Sbillf	{'�', ".-."},	/* er */
24754622Sbillf	{'�', "..."},	/* es */
24854622Sbillf	{'�', "-"},		/* te */
24954622Sbillf	{'�', "..-"},	/* u */
25054622Sbillf	{'�', "..-."},	/* ef */
25154622Sbillf	{'�', "...."},	/* kha */
25254622Sbillf	{'�', "-.-."},	/* ce */
25354622Sbillf	{'�', "---."},	/* che */
25454622Sbillf	{'�', "----"},	/* sha */
25554622Sbillf	{'�', "--.-"},	/* shcha */
25654622Sbillf	{'�', "-.--"},	/* yi */
25754622Sbillf	{'�', "-..-"},	/* myakhkij znak */
25854622Sbillf	{'�', "..-.."},	/* ae */
25954622Sbillf	{'�', "..--"},	/* yu */
26054622Sbillf	{'�', ".-.-"},	/* ya */
26110352Sjoerg
26254622Sbillf	{'\0', ""}
26310352Sjoerg};
26410352Sjoerg
26510352Sjoergvoid            show(const char *), play(const char *), morse(char);
26657527Sjoergvoid		ttyout(const char *);
26757527Sjoergvoid		sighandler(int);
26810352Sjoerg
269147110Sjoerg#define GETOPTOPTS "c:d:ef:lsw:"
27057527Sjoerg#define USAGE \
271147110Sjoerg"usage: morse [-els] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
27257527Sjoerg
273121945Sphkstatic int      pflag, lflag, sflag, eflag;
274147110Sjoergstatic int      wpm = 20;	/* effective words per minute */
275147110Sjoergstatic int      cpm;		/* effective words per minute between
276147110Sjoerg				 * characters */
27710352Sjoerg#define FREQUENCY 600
27810352Sjoergstatic int      freq = FREQUENCY;
27957527Sjoergstatic char	*device;	/* for tty-controlled generator */
28010352Sjoerg
28110352Sjoerg#define DASH_LEN 3
28210352Sjoerg#define CHAR_SPACE 3
28310352Sjoerg#define WORD_SPACE (7 - CHAR_SPACE - 1)
28410352Sjoergstatic float    dot_clock;
285147110Sjoergstatic float    cdot_clock;
28657527Sjoergint             spkr, line;
28757527Sjoergstruct termios	otty, ntty;
28857527Sjoergint		olflags;
28957527Sjoerg
29057527Sjoerg#ifdef SPEAKER
29110352Sjoergtone_t          sound;
29257527Sjoerg#undef GETOPTOPTS
293147110Sjoerg#define GETOPTOPTS "c:d:ef:lpsw:"
29457527Sjoerg#undef USAGE
29557527Sjoerg#define USAGE \
296147110Sjoerg"usage: morse [-elps] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
29710352Sjoerg#endif
29810352Sjoerg
29978793Sachestatic const struct morsetab *hightab;
30010352Sjoerg
30110352Sjoergint
30210352Sjoergmain(int argc, char **argv)
3032490Sjkh{
30457527Sjoerg	int    ch, lflags;
30578793Sache	char  *p, *codeset;
3062490Sjkh
30757527Sjoerg	while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1)
30810352Sjoerg		switch ((char) ch) {
309147110Sjoerg 		case 'c':
310147110Sjoerg 			cpm = atoi(optarg);
311147110Sjoerg 			break;
31257527Sjoerg		case 'd':
31357527Sjoerg			device = optarg;
31457527Sjoerg			break;
31557527Sjoerg		case 'e':
31657527Sjoerg			eflag = 1;
31757527Sjoerg			setvbuf(stdout, 0, _IONBF, 0);
31857527Sjoerg			break;
31910352Sjoerg		case 'f':
32010352Sjoerg			freq = atoi(optarg);
32110352Sjoerg			break;
322121945Sphk		case 'l':
323121945Sphk			lflag = 1;
324121945Sphk			break;
32557527Sjoerg#ifdef SPEAKER
32610352Sjoerg		case 'p':
32710352Sjoerg			pflag = 1;
32810352Sjoerg			break;
32957527Sjoerg#endif
3302490Sjkh		case 's':
3312490Sjkh			sflag = 1;
3322490Sjkh			break;
33310352Sjoerg		case 'w':
33410352Sjoerg			wpm = atoi(optarg);
33510352Sjoerg			break;
3362490Sjkh		case '?':
3372490Sjkh		default:
33857527Sjoerg			fputs(USAGE, stderr);
3392490Sjkh			exit(1);
3402490Sjkh		}
341121945Sphk	if (sflag && lflag) {
342121945Sphk		fputs("morse: only one of -l and -s allowed\n", stderr);
34310352Sjoerg		exit(1);
34410352Sjoerg	}
345121945Sphk	if ((pflag || device) && (sflag || lflag)) {
346121945Sphk		fputs("morse: only one of -p, -d and -l, -s allowed\n", stderr);
347121945Sphk		exit(1);
348121945Sphk	}
349147110Sjoerg	if (cpm == 0)
350147110Sjoerg		cpm = wpm;
351147110Sjoerg	if ((pflag || device) && ((wpm < 1) || (wpm > 60) || (cpm < 1) || (cpm > 60))) {
35210352Sjoerg		fputs("morse: insane speed\n", stderr);
35310352Sjoerg		exit(1);
35410352Sjoerg	}
35557527Sjoerg	if ((pflag || device) && (freq == 0))
35610352Sjoerg		freq = FREQUENCY;
35710352Sjoerg
35810352Sjoerg#ifdef SPEAKER
35910352Sjoerg	if (pflag) {
36010352Sjoerg		if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
36110352Sjoerg			perror(SPEAKER);
36210352Sjoerg			exit(1);
36310352Sjoerg		}
36457527Sjoerg	} else
36557527Sjoerg#endif
36657527Sjoerg	if (device) {
36757527Sjoerg		if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) {
36857527Sjoerg			perror("open tty line");
36957527Sjoerg			exit(1);
37057527Sjoerg		}
37157527Sjoerg		if (tcgetattr(line, &otty) == -1) {
37257527Sjoerg			perror("tcgetattr() failed");
37357527Sjoerg			exit(1);
37457527Sjoerg		}
37557527Sjoerg		ntty = otty;
37657527Sjoerg		ntty.c_cflag |= CLOCAL;
37757527Sjoerg		tcsetattr(line, TCSANOW, &ntty);
37857527Sjoerg		lflags = fcntl(line, F_GETFL);
37957527Sjoerg		lflags &= ~O_NONBLOCK;
38057527Sjoerg		fcntl(line, F_SETFL, &lflags);
38157527Sjoerg		ioctl(line, TIOCMGET, &lflags);
38257527Sjoerg		lflags &= ~TIOCM_RTS;
38357527Sjoerg		olflags = lflags;
38457527Sjoerg		ioctl(line, TIOCMSET, &lflags);
38557527Sjoerg		(void)signal(SIGHUP, sighandler);
38657527Sjoerg		(void)signal(SIGINT, sighandler);
38757527Sjoerg		(void)signal(SIGQUIT, sighandler);
38857527Sjoerg		(void)signal(SIGTERM, sighandler);
38957527Sjoerg	}
39057527Sjoerg	if (pflag || device) {
39110352Sjoerg		dot_clock = wpm / 2.4;		/* dots/sec */
39210352Sjoerg		dot_clock = 1 / dot_clock;	/* duration of a dot */
39310352Sjoerg		dot_clock = dot_clock / 2;	/* dot_clock runs at twice */
39410352Sjoerg						/* the dot rate */
39510352Sjoerg		dot_clock = dot_clock * 100;	/* scale for ioctl */
396147110Sjoerg
397147110Sjoerg		cdot_clock = cpm / 2.4;		/* dots/sec */
398147110Sjoerg		cdot_clock = 1 / cdot_clock;	/* duration of a dot */
399147110Sjoerg		cdot_clock = cdot_clock / 2;	/* dot_clock runs at twice */
400147110Sjoerg						/* the dot rate */
401147110Sjoerg		cdot_clock = cdot_clock * 100;	/* scale for ioctl */
40210352Sjoerg	}
40357527Sjoerg
4042490Sjkh	argc -= optind;
4052490Sjkh	argv += optind;
4062490Sjkh
40778793Sache	if (setlocale(LC_CTYPE, "") != NULL &&
40878793Sache	    *(codeset = nl_langinfo(CODESET)) != '\0') {
40978793Sache		if (strcmp(codeset, "KOI8-R") == 0)
41010352Sjoerg			hightab = koi8rtab;
41178793Sache		else if (strcmp(codeset, "ISO8859-1") == 0 ||
41278793Sache			 strcmp(codeset, "ISO8859-15") == 0)
413129114Sdds			hightab = iso8859_1tab;
414129114Sdds		else if (strcmp(codeset, "ISO8859-7") == 0)
415129114Sdds			hightab = iso8859_7tab;
41610352Sjoerg	}
41710352Sjoerg
418121945Sphk	if (lflag)
419121945Sphk		printf("m");
42010352Sjoerg	if (*argv) {
4212490Sjkh		do {
42210352Sjoerg			for (p = *argv; *p; ++p) {
42357527Sjoerg				if (eflag)
42457527Sjoerg					putchar(*p);
42529018Sache				morse(*p);
42610352Sjoerg			}
42757527Sjoerg			if (eflag)
42857527Sjoerg				putchar(' ');
42929018Sache			morse(' ');
4302490Sjkh		} while (*++argv);
43110352Sjoerg	} else {
43257527Sjoerg		while ((ch = getchar()) != EOF) {
43357527Sjoerg			if (eflag)
43457527Sjoerg				putchar(ch);
43510352Sjoerg			morse(ch);
43657527Sjoerg		}
43710352Sjoerg	}
43857527Sjoerg	if (device)
43957527Sjoerg		tcsetattr(line, TCSANOW, &otty);
44010352Sjoerg	exit(0);
4412490Sjkh}
4422490Sjkh
44310352Sjoergvoid
44410352Sjoergmorse(char c)
4452490Sjkh{
44654622Sbillf	const struct morsetab *m;
44710352Sjoerg
44829018Sache	if (isalpha((unsigned char)c))
44929018Sache		c = tolower((unsigned char)c);
45010352Sjoerg	if ((c == '\r') || (c == '\n'))
45110352Sjoerg		c = ' ';
45210352Sjoerg	if (c == ' ') {
453121945Sphk		if (pflag)
45410352Sjoerg			play(" ");
455121945Sphk		else if (device)
45657527Sjoerg			ttyout(" ");
457121945Sphk		else if (lflag)
458121945Sphk			printf("\n");
459121945Sphk		else
46010352Sjoerg			show("");
461121945Sphk		return;
46210352Sjoerg	}
46310352Sjoerg	for (m = ((unsigned char)c < 0x80? mtab: hightab);
46478793Sache	     m != NULL && m->inchar != '\0';
46510352Sjoerg	     m++) {
46610352Sjoerg		if (m->inchar == c) {
46710352Sjoerg			if (pflag) {
46810352Sjoerg				play(m->morse);
46957527Sjoerg			} else if (device) {
47057527Sjoerg				ttyout(m->morse);
47110352Sjoerg			} else
47210352Sjoerg				show(m->morse);
47310352Sjoerg		}
47410352Sjoerg	}
4752490Sjkh}
4762490Sjkh
47710352Sjoergvoid
47810352Sjoergshow(const char *s)
4792490Sjkh{
480121945Sphk	if (lflag) {
481121945Sphk		printf("%s ", s);
482121945Sphk	} else if (sflag) {
483121945Sphk		printf(" %s\n", s);
484121945Sphk	} else {
48510352Sjoerg		for (; *s; ++s)
48610352Sjoerg			printf(" %s", *s == '.' ? "dit" : "dah");
487121945Sphk		printf("\n");
488121945Sphk	}
4892490Sjkh}
49010352Sjoerg
49110352Sjoergvoid
49210352Sjoergplay(const char *s)
49310352Sjoerg{
49410352Sjoerg#ifdef SPEAKER
49510352Sjoerg	const char *c;
49610352Sjoerg
49710352Sjoerg	for (c = s; *c != '\0'; c++) {
49829018Sache		switch (*c) {
49910352Sjoerg		case '.':
50010352Sjoerg			sound.frequency = freq;
50110352Sjoerg			sound.duration = dot_clock;
50210352Sjoerg			break;
50310352Sjoerg		case '-':
50410352Sjoerg			sound.frequency = freq;
50510352Sjoerg			sound.duration = dot_clock * DASH_LEN;
50610352Sjoerg			break;
50710352Sjoerg		case ' ':
50810352Sjoerg			sound.frequency = 0;
509147110Sjoerg			sound.duration = cdot_clock * WORD_SPACE;
51010352Sjoerg			break;
51110352Sjoerg		default:
51210352Sjoerg			sound.duration = 0;
51310352Sjoerg		}
51410352Sjoerg		if (sound.duration) {
51510352Sjoerg			if (ioctl(spkr, SPKRTONE, &sound) == -1) {
51610352Sjoerg				perror("ioctl play");
51710352Sjoerg				exit(1);
51810352Sjoerg			}
51910352Sjoerg		}
52010352Sjoerg		sound.frequency = 0;
52110352Sjoerg		sound.duration = dot_clock;
52210352Sjoerg		if (ioctl(spkr, SPKRTONE, &sound) == -1) {
52310352Sjoerg			perror("ioctl rest");
52410352Sjoerg			exit(1);
52510352Sjoerg		}
52610352Sjoerg	}
52710352Sjoerg	sound.frequency = 0;
528147110Sjoerg	sound.duration = cdot_clock * CHAR_SPACE;
52910352Sjoerg	ioctl(spkr, SPKRTONE, &sound);
53010352Sjoerg#endif
53110352Sjoerg}
53257527Sjoerg
53357527Sjoergvoid
53457527Sjoergttyout(const char *s)
53557527Sjoerg{
53657527Sjoerg	const char *c;
53757527Sjoerg	int duration, on, lflags;
53857527Sjoerg
53957527Sjoerg	for (c = s; *c != '\0'; c++) {
54057527Sjoerg		switch (*c) {
54157527Sjoerg		case '.':
54257527Sjoerg			on = 1;
54357527Sjoerg			duration = dot_clock;
54457527Sjoerg			break;
54557527Sjoerg		case '-':
54657527Sjoerg			on = 1;
54757527Sjoerg			duration = dot_clock * DASH_LEN;
54857527Sjoerg			break;
54957527Sjoerg		case ' ':
55057527Sjoerg			on = 0;
551147110Sjoerg			duration = cdot_clock * WORD_SPACE;
55257527Sjoerg			break;
55357527Sjoerg		default:
55457527Sjoerg			on = 0;
55557527Sjoerg			duration = 0;
55657527Sjoerg		}
55757527Sjoerg		if (on) {
55857527Sjoerg			ioctl(line, TIOCMGET, &lflags);
55957527Sjoerg			lflags |= TIOCM_RTS;
56057527Sjoerg			ioctl(line, TIOCMSET, &lflags);
56157527Sjoerg		}
56257527Sjoerg		duration *= 10000;
56357527Sjoerg		if (duration)
56457527Sjoerg			usleep(duration);
56557527Sjoerg		ioctl(line, TIOCMGET, &lflags);
56657527Sjoerg		lflags &= ~TIOCM_RTS;
56757527Sjoerg		ioctl(line, TIOCMSET, &lflags);
56857527Sjoerg		duration = dot_clock * 10000;
56957527Sjoerg		usleep(duration);
57057527Sjoerg	}
571147110Sjoerg	duration = cdot_clock * CHAR_SPACE * 10000;
57257527Sjoerg	usleep(duration);
57357527Sjoerg}
57457527Sjoerg
57557527Sjoergvoid
57657527Sjoergsighandler(int signo)
57757527Sjoerg{
57857527Sjoerg
57957527Sjoerg	ioctl(line, TIOCMSET, &olflags);
58057527Sjoerg	tcsetattr(line, TCSANOW, &otty);
58157527Sjoerg
58257527Sjoerg	signal(signo, SIG_DFL);
58357527Sjoerg	(void)kill(getpid(), signo);
58457527Sjoerg}
585