morse.c revision 147110
11722Sjkh/*
21722Sjkh * Copyright (c) 1988, 1993
31722Sjkh *	The Regents of the University of California.  All rights reserved.
41722Sjkh *
51722Sjkh * Redistribution and use in source and binary forms, with or without
61722Sjkh * modification, are permitted provided that the following conditions
71722Sjkh * are met:
81722Sjkh * 1. Redistributions of source code must retain the above copyright
91722Sjkh *    notice, this list of conditions and the following disclaimer.
101722Sjkh * 2. Redistributions in binary form must reproduce the above copyright
111722Sjkh *    notice, this list of conditions and the following disclaimer in the
121722Sjkh *    documentation and/or other materials provided with the distribution.
131722Sjkh * 3. All advertising materials mentioning features or use of this software
141722Sjkh *    must display the following acknowledgement:
151722Sjkh *	This product includes software developed by the University of
161722Sjkh *	California, Berkeley and its contributors.
171722Sjkh * 4. Neither the name of the University nor the names of its contributors
181722Sjkh *    may be used to endorse or promote products derived from this software
191722Sjkh *    without specific prior written permission.
201722Sjkh *
211722Sjkh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221722Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231722Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241722Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2556995Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2656995Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271722Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281722Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291722Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301722Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311722Sjkh * SUCH DAMAGE.
321722Sjkh */
338857Srgrimes
341722Sjkh/*
3570884Sjoe * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM)
3670884Sjoe * <lyndon@orthanc.com>
3770884Sjoe */
3870884Sjoe
3929453Scharnier#ifndef lint
4029453Scharnierstatic const char copyright[] =
4170124Sjoe"@(#) Copyright (c) 1988, 1993\n\
4229453Scharnier	The Regents of the University of California.  All rights reserved.\n";
431722Sjkh#endif /* not lint */
4429453Scharnier
451722Sjkh#ifndef lint
461722Sjkh#if 0
471722Sjkhstatic char sccsid[] = "@(#)morse.c	8.1 (Berkeley) 5/31/93";
481722Sjkh#endif
491722Sjkhstatic const char rcsid[] =
501722Sjkh "$FreeBSD: head/games/morse/morse.c 147110 2005-06-07 19:01:41Z joerg $";
511722Sjkh#endif /* not lint */
521722Sjkh
531722Sjkh#include <sys/time.h>
541722Sjkh
551722Sjkh#include <ctype.h>
561722Sjkh#include <fcntl.h>
571722Sjkh#include <langinfo.h>
5870884Sjoe#include <locale.h>
5970884Sjoe#include <signal.h>
601722Sjkh#include <stdio.h>
611722Sjkh#include <stdlib.h>
621722Sjkh#include <string.h>
631722Sjkh#include <termios.h>
641722Sjkh#include <unistd.h>
6570884Sjoe
6670884Sjoe#ifdef SPEAKER
6770884Sjoe#include <machine/speaker.h>
6870884Sjoe#endif
6970884Sjoe
7070884Sjoestruct morsetab {
7170884Sjoe	char            inchar;
7270884Sjoe	char           *morse;
7370884Sjoe};
7470884Sjoe
7570884Sjoestatic const struct morsetab mtab[] = {
7693435Sluigi
77153687Sceri	/* letters */
7870884Sjoe
791722Sjkh	{'a', ".-"},
801722Sjkh	{'b', "-..."},
811722Sjkh	{'c', "-.-."},
821722Sjkh	{'d', "-.."},
831722Sjkh	{'e', "."},
8468750Sjoe	{'f', "..-."},
8570884Sjoe	{'g', "--."},
8670884Sjoe	{'h', "...."},
87153687Sceri	{'i', ".."},
8870884Sjoe	{'j', ".---"},
891722Sjkh	{'k', "-.-"},
901722Sjkh	{'l', ".-.."},
911722Sjkh	{'m', "--"},
921722Sjkh	{'n', "-."},
9370884Sjoe	{'o', "---"},
9470884Sjoe	{'p', ".--."},
951722Sjkh	{'q', "--.-"},
961722Sjkh	{'r', ".-."},
971722Sjkh	{'s', "..."},
9870884Sjoe	{'t', "-"},
991722Sjkh	{'u', "..-"},
10070884Sjoe	{'v', "...-"},
1011722Sjkh	{'w', ".--"},
1026696Sphk	{'x', "-..-"},
1036696Sphk	{'y', "-.--"},
1041722Sjkh	{'z', "--.."},
1051722Sjkh
1061722Sjkh	/* digits */
1071722Sjkh
1081722Sjkh	{'0', "-----"},
1091722Sjkh	{'1', ".----"},
1101722Sjkh	{'2', "..---"},
111153687Sceri	{'3', "...--"},
112153687Sceri	{'4', "....-"},
1131722Sjkh	{'5', "....."},
1141722Sjkh	{'6', "-...."},
1151722Sjkh	{'7', "--..."},
1168857Srgrimes	{'8', "---.."},
1171722Sjkh	{'9', "----."},
1181722Sjkh
1191722Sjkh	/* punctuation */
1201722Sjkh
1211722Sjkh	{',', "--..--"},
1221722Sjkh	{'.', ".-.-.-"},
12370884Sjoe	{'"', ".-..-."},
12470884Sjoe	{'!', "..--."},
1251722Sjkh	{'?', "..--.."},
12670884Sjoe	{'/', "-..-."},
12770884Sjoe	{'-', "-....-"},
12870884Sjoe	{'=', "-...-"},		/* BT */
1298857Srgrimes	{':', "---..."},
13070884Sjoe	{';', "-.-.-."},
13170884Sjoe	{'(', "-.--."},		/* KN */
13270884Sjoe	{')', "-.--.-"},
13370884Sjoe	{'$', "...-..-"},
13470884Sjoe	{'+', ".-.-."},		/* AR */
13570884Sjoe	{'@', ".--.-."},	/* AC */
13669413Sluigi
13770884Sjoe	/* prosigns without already assigned values */
13870884Sjoe
13970884Sjoe	{'#', ".-..."},		/* AS */
14070884Sjoe	{'&', "...-.-"},	/* SK */
14170884Sjoe	{'*', "...-."},		/* VE */
14270884Sjoe	{'%', "-...-.-"},	/* BK */
14370884Sjoe
14470884Sjoe	{'\0', ""}
14570884Sjoe};
14670884Sjoe
14770884Sjoe
1481722Sjkhstatic const struct morsetab iso8859_1tab[] = {
14970884Sjoe	{'�', ".--.-"},
15070884Sjoe	{'�', ".--.-"},
15170884Sjoe	{'�', ".--.-"},
15270884Sjoe	{'�', ".-.-"},
15370884Sjoe	{'�', "-.-.."},
15470113Sjoe	{'�', "..-.."},
15570113Sjoe	{'�', "..-.."},
1561722Sjkh	{'�', "-..-."},
15770884Sjoe	{'�', "---."},
15870884Sjoe	{'�', "..--"},
15970884Sjoe
16070884Sjoe	{'\0', ""}
16170884Sjoe};
16270884Sjoe
16370884Sjoestatic const struct morsetab iso8859_7tab[] = {
16470884Sjoe	/*
16570884Sjoe	 * The greek alphabet; you'll need an 8859-7 font in order
16670884Sjoe	 * to see the actual characters.
16770884Sjoe	 * This table does not implement:
16870884Sjoe	 * - the special sequences for the seven diphthongs,
16970884Sjoe	 * - the punctuation differences.
17070884Sjoe	 * Implementing these features would introduce too many
17170884Sjoe	 * special-cases in the program's main loop.
17270884Sjoe	 * The diphtong sequences are:
17370884Sjoe	 * alpha iota		.-.-
17470884Sjoe	 * alpha upsilon	..--
17570884Sjoe	 * epsilon upsilon	---.
1761722Sjkh	 * eta upsilon		...-
1771722Sjkh	 * omikron iota		---..
17870884Sjoe	 * omikron upsilon	..-
17970884Sjoe	 * upsilon iota		.---
1801722Sjkh	 * The different punctuation symbols are:
18170884Sjoe	 * ;	..-.-
18270884Sjoe	 * !	--..--
1831722Sjkh	 */
18470884Sjoe	{'�', ".-"},	/* alpha */
18570884Sjoe	{'�', ".-"},	/* alpha with acute */
18670884Sjoe	{'�', "-..."},	/* beta */
1871722Sjkh	{'�', "--."},	/* gamma */
18870884Sjoe	{'�', "-.."},	/* delta */
1891722Sjkh	{'�', "."},	/* epsilon */
19070884Sjoe	{'�', "."},	/* epsilon with acute */
1911722Sjkh	{'�', "--.."},	/* zeta */
19270884Sjoe	{'�', "...."},	/* eta */
19370884Sjoe	{'�', "...."},	/* eta with acute */
19470884Sjoe	{'�', "-.-."},	/* theta */
19570884Sjoe	{'�', ".."},	/* iota */
1961722Sjkh	{'�', ".."},	/* iota with acute */
19770884Sjoe	{'�', ".."},	/* iota with diairesis */
19870884Sjoe	{'�', ".."},	/* iota with acute and diairesis */
1991722Sjkh	{'�', "-.-"},	/* kappa */
20070884Sjoe	{'�', ".-.."},	/* lamda */
20170884Sjoe	{'�', "--"},	/* mu */
20270884Sjoe	{'�', "-."},	/* nu */
20370884Sjoe	{'�', "-..-"},	/* xi */
20470884Sjoe	{'�', "---"},	/* omicron */
20570884Sjoe	{'�', "---"},	/* omicron with acute */
20670884Sjoe	{'�', ".--."},	/* pi */
20770884Sjoe	{'�', ".-."},	/* rho */
20870884Sjoe	{'�', "..."},	/* sigma */
20970124Sjoe	{'�', "..."},	/* final sigma */
2101722Sjkh	{'�', "-"},	/* tau */
21170884Sjoe	{'�', "-.--"},	/* upsilon */
21270884Sjoe	{'�', "-.--"},	/* upsilon with acute */
21370884Sjoe	{'�', "-.--"},	/* upsilon and diairesis */
2146696Sphk	{'�', "-.--"},	/* upsilon with acute and diairesis */
21570884Sjoe	{'�', "..-."},	/* phi */
2161722Sjkh	{'�', "----"},	/* chi */
21770884Sjoe	{'�', "--.-"},	/* psi */
2181722Sjkh	{'�', ".--"},	/* omega */
2191722Sjkh	{'�', ".--"},	/* omega with acute */
2201722Sjkh
2211722Sjkh	{'\0', ""}
2221722Sjkh};
22370884Sjoe
22470884Sjoestatic const struct morsetab koi8rtab[] = {
22570884Sjoe	/*
22670884Sjoe	 * the cyrillic alphabet; you'll need a KOI8R font in order
22770884Sjoe	 * to see the actual characters
2281722Sjkh	 */
2291722Sjkh	{'�', ".-"},		/* a */
2301722Sjkh	{'�', "-..."},	/* be */
2311722Sjkh	{'�', ".--"},	/* ve */
2321722Sjkh	{'�', "--."},	/* ge */
2331722Sjkh	{'�', "-.."},	/* de */
2341722Sjkh	{'�', "."},		/* ye */
2351722Sjkh	{'�', "."},         	/* yo, the same as ye */
2361722Sjkh	{'�', "...-"},	/* she */
2371722Sjkh	{'�', "--.."},	/* ze */
2381722Sjkh	{'�', ".."},		/* i */
2391722Sjkh	{'�', ".---"},	/* i kratkoye */
2408857Srgrimes	{'�', "-.-"},	/* ka */
2411722Sjkh	{'�', ".-.."},	/* el */
2421722Sjkh	{'�', "--"},		/* em */
2431722Sjkh	{'�', "-."},		/* en */
2441722Sjkh	{'�', "---"},	/* o */
245153687Sceri	{'�', ".--."},	/* pe */
24668750Sjoe	{'�', ".-."},	/* er */
2471722Sjkh	{'�', "..."},	/* es */
2481722Sjkh	{'�', "-"},		/* te */
2491722Sjkh	{'�', "..-"},	/* u */
2501722Sjkh	{'�', "..-."},	/* ef */
2511722Sjkh	{'�', "...."},	/* kha */
2521722Sjkh	{'�', "-.-."},	/* ce */
2531722Sjkh	{'�', "---."},	/* che */
2541722Sjkh	{'�', "----"},	/* sha */
25570884Sjoe	{'�', "--.-"},	/* shcha */
25629453Scharnier	{'�', "-.--"},	/* yi */
25770884Sjoe	{'�', "-..-"},	/* myakhkij znak */
25870884Sjoe	{'�', "..-.."},	/* ae */
25970884Sjoe	{'�', "..--"},	/* yu */
26070884Sjoe	{'�', ".-.-"},	/* ya */
26170884Sjoe
26270884Sjoe	{'\0', ""}
2631722Sjkh};
2641722Sjkh
2651722Sjkhvoid            show(const char *), play(const char *), morse(char);
2661722Sjkhvoid		ttyout(const char *);
2671722Sjkhvoid		sighandler(int);
26870884Sjoe
26970884Sjoe#define GETOPTOPTS "c:d:ef:lsw:"
27070884Sjoe#define USAGE \
27170884Sjoe"usage: morse [-els] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
27270884Sjoe
2731722Sjkhstatic int      pflag, lflag, sflag, eflag;
27470884Sjoestatic int      wpm = 20;	/* effective words per minute */
27570884Sjoestatic int      cpm;		/* effective words per minute between
27670884Sjoe				 * characters */
2771722Sjkh#define FREQUENCY 600
27870884Sjoestatic int      freq = FREQUENCY;
27970884Sjoestatic char	*device;	/* for tty-controlled generator */
28070884Sjoe
28170884Sjoe#define DASH_LEN 3
28270884Sjoe#define CHAR_SPACE 3
2831722Sjkh#define WORD_SPACE (7 - CHAR_SPACE - 1)
28470884Sjoestatic float    dot_clock;
28570884Sjoestatic float    cdot_clock;
28670884Sjoeint             spkr, line;
28770884Sjoestruct termios	otty, ntty;
28870884Sjoeint		olflags;
28970884Sjoe
29070884Sjoe#ifdef SPEAKER
29170884Sjoetone_t          sound;
29270884Sjoe#undef GETOPTOPTS
29370884Sjoe#define GETOPTOPTS "c:d:ef:lpsw:"
29470884Sjoe#undef USAGE
29570884Sjoe#define USAGE \
29670884Sjoe"usage: morse [-elps] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n"
29770884Sjoe#endif
29870884Sjoe
29970884Sjoestatic const struct morsetab *hightab;
300153687Sceri
301153687Sceriint
30270884Sjoemain(int argc, char **argv)
30370884Sjoe{
30470884Sjoe	int    ch, lflags;
30570884Sjoe	char  *p, *codeset;
30670884Sjoe
30770884Sjoe	while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1)
30870884Sjoe		switch ((char) ch) {
30970884Sjoe 		case 'c':
31070884Sjoe 			cpm = atoi(optarg);
31170884Sjoe 			break;
31270884Sjoe		case 'd':
31370884Sjoe			device = optarg;
31470884Sjoe			break;
31570884Sjoe		case 'e':
31670884Sjoe			eflag = 1;
31770884Sjoe			setvbuf(stdout, 0, _IONBF, 0);
31870884Sjoe			break;
31970884Sjoe		case 'f':
32070884Sjoe			freq = atoi(optarg);
32170884Sjoe			break;
3221722Sjkh		case 'l':
32370884Sjoe			lflag = 1;
32470884Sjoe			break;
32570884Sjoe#ifdef SPEAKER
32670884Sjoe		case 'p':
3271722Sjkh			pflag = 1;
32870884Sjoe			break;
3291722Sjkh#endif
3301722Sjkh		case 's':
3311722Sjkh			sflag = 1;
3321722Sjkh			break;
3331722Sjkh		case 'w':
33470884Sjoe			wpm = atoi(optarg);
3351722Sjkh			break;
33670884Sjoe		case '?':
33770884Sjoe		default:
3381722Sjkh			fputs(USAGE, stderr);
33970884Sjoe			exit(1);
34070884Sjoe		}
34170884Sjoe	if (sflag && lflag) {
34270884Sjoe		fputs("morse: only one of -l and -s allowed\n", stderr);
34370884Sjoe		exit(1);
34470884Sjoe	}
34570884Sjoe	if ((pflag || device) && (sflag || lflag)) {
34670884Sjoe		fputs("morse: only one of -p, -d and -l, -s allowed\n", stderr);
34770884Sjoe		exit(1);
34870884Sjoe	}
34970884Sjoe	if (cpm == 0)
35070884Sjoe		cpm = wpm;
35170884Sjoe	if ((pflag || device) && ((wpm < 1) || (wpm > 60) || (cpm < 1) || (cpm > 60))) {
35270884Sjoe		fputs("morse: insane speed\n", stderr);
35370884Sjoe		exit(1);
35470884Sjoe	}
35570884Sjoe	if ((pflag || device) && (freq == 0))
35670884Sjoe		freq = FREQUENCY;
35770884Sjoe
35870884Sjoe#ifdef SPEAKER
35970884Sjoe	if (pflag) {
3601722Sjkh		if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) {
3611722Sjkh			perror(SPEAKER);
3621722Sjkh			exit(1);
3631722Sjkh		}
3641722Sjkh	} else
36570884Sjoe#endif
3661722Sjkh	if (device) {
36770884Sjoe		if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) {
36870884Sjoe			perror("open tty line");
36970884Sjoe			exit(1);
37070884Sjoe		}
37170884Sjoe		if (tcgetattr(line, &otty) == -1) {
37270884Sjoe			perror("tcgetattr() failed");
37370884Sjoe			exit(1);
37470884Sjoe		}
3751722Sjkh		ntty = otty;
3761722Sjkh		ntty.c_cflag |= CLOCAL;
3771722Sjkh		tcsetattr(line, TCSANOW, &ntty);
3781722Sjkh		lflags = fcntl(line, F_GETFL);
3791722Sjkh		lflags &= ~O_NONBLOCK;
3801722Sjkh		fcntl(line, F_SETFL, &lflags);
38170884Sjoe		ioctl(line, TIOCMGET, &lflags);
3821722Sjkh		lflags &= ~TIOCM_RTS;
38370884Sjoe		olflags = lflags;
38470884Sjoe		ioctl(line, TIOCMSET, &lflags);
3851722Sjkh		(void)signal(SIGHUP, sighandler);
3861722Sjkh		(void)signal(SIGINT, sighandler);
3871722Sjkh		(void)signal(SIGQUIT, sighandler);
3881722Sjkh		(void)signal(SIGTERM, sighandler);
3891722Sjkh	}
39070884Sjoe	if (pflag || device) {
3911722Sjkh		dot_clock = wpm / 2.4;		/* dots/sec */
39270884Sjoe		dot_clock = 1 / dot_clock;	/* duration of a dot */
3931722Sjkh		dot_clock = dot_clock / 2;	/* dot_clock runs at twice */
39470884Sjoe						/* the dot rate */
39570884Sjoe		dot_clock = dot_clock * 100;	/* scale for ioctl */
39670884Sjoe
3971722Sjkh		cdot_clock = cpm / 2.4;		/* dots/sec */
39870884Sjoe		cdot_clock = 1 / cdot_clock;	/* duration of a dot */
39970884Sjoe		cdot_clock = cdot_clock / 2;	/* dot_clock runs at twice */
40070884Sjoe						/* the dot rate */
40170884Sjoe		cdot_clock = cdot_clock * 100;	/* scale for ioctl */
40270884Sjoe	}
40370884Sjoe
40470884Sjoe	argc -= optind;
4051722Sjkh	argv += optind;
40670884Sjoe
40770884Sjoe	if (setlocale(LC_CTYPE, "") != NULL &&
40870884Sjoe	    *(codeset = nl_langinfo(CODESET)) != '\0') {
40970884Sjoe		if (strcmp(codeset, "KOI8-R") == 0)
41070884Sjoe			hightab = koi8rtab;
4111722Sjkh		else if (strcmp(codeset, "ISO8859-1") == 0 ||
41270884Sjoe			 strcmp(codeset, "ISO8859-15") == 0)
41370884Sjoe			hightab = iso8859_1tab;
41470884Sjoe		else if (strcmp(codeset, "ISO8859-7") == 0)
41570884Sjoe			hightab = iso8859_7tab;
41670884Sjoe	}
41793435Sluigi
418153687Sceri	if (lflag)
41970884Sjoe		printf("m");
42070884Sjoe	if (*argv) {
42170884Sjoe		do {
42270884Sjoe			for (p = *argv; *p; ++p) {
42370884Sjoe				if (eflag)
42470884Sjoe					putchar(*p);
42570884Sjoe				morse(*p);
4261722Sjkh			}
4271722Sjkh			if (eflag)
4281722Sjkh				putchar(' ');
4291722Sjkh			morse(' ');
4301722Sjkh		} while (*++argv);
43170884Sjoe	} else {
43270884Sjoe		while ((ch = getchar()) != EOF) {
4331722Sjkh			if (eflag)
43470884Sjoe				putchar(ch);
43570884Sjoe			morse(ch);
43670884Sjoe		}
43770884Sjoe	}
43870884Sjoe	if (device)
43970884Sjoe		tcsetattr(line, TCSANOW, &otty);
44070884Sjoe	exit(0);
44170884Sjoe}
44270884Sjoe
44370884Sjoevoid
44470884Sjoemorse(char c)
44570884Sjoe{
44670884Sjoe	const struct morsetab *m;
4471722Sjkh
4481722Sjkh	if (isalpha((unsigned char)c))
4491722Sjkh		c = tolower((unsigned char)c);
4501722Sjkh	if ((c == '\r') || (c == '\n'))
4511722Sjkh		c = ' ';
45270884Sjoe	if (c == ' ') {
4531722Sjkh		if (pflag)
454153687Sceri			play(" ");
45570884Sjoe		else if (device)
456153687Sceri			ttyout(" ");
457153687Sceri		else if (lflag)
458153687Sceri			printf("\n");
459153687Sceri		else
460153687Sceri			show("");
4611722Sjkh		return;
4621722Sjkh	}
4631722Sjkh	for (m = ((unsigned char)c < 0x80? mtab: hightab);
464153687Sceri	     m != NULL && m->inchar != '\0';
465153687Sceri	     m++) {
466153687Sceri		if (m->inchar == c) {
467153687Sceri			if (pflag) {
468153687Sceri				play(m->morse);
469153687Sceri			} else if (device) {
470153687Sceri				ttyout(m->morse);
471153687Sceri			} else
472153687Sceri				show(m->morse);
473153687Sceri		}
474153687Sceri	}
475153687Sceri}
476153687Sceri
477153687Scerivoid
47868750Sjoeshow(const char *s)
47968750Sjoe{
48070884Sjoe	if (lflag) {
48168750Sjoe		printf("%s ", s);
48270884Sjoe	} else if (sflag) {
48370884Sjoe		printf(" %s\n", s);
48468750Sjoe	} else {
48568750Sjoe		for (; *s; ++s)
48668750Sjoe			printf(" %s", *s == '.' ? "dit" : "dah");
4871722Sjkh		printf("\n");
4881722Sjkh	}
48970884Sjoe}
49070884Sjoe
4911722Sjkhvoid
49270884Sjoeplay(const char *s)
49370884Sjoe{
49470884Sjoe#ifdef SPEAKER
4951722Sjkh	const char *c;
49670884Sjoe
49770884Sjoe	for (c = s; *c != '\0'; c++) {
49870884Sjoe		switch (*c) {
49970884Sjoe		case '.':
50070884Sjoe			sound.frequency = freq;
5011722Sjkh			sound.duration = dot_clock;
50270884Sjoe			break;
50370884Sjoe		case '-':
50470884Sjoe			sound.frequency = freq;
50570884Sjoe			sound.duration = dot_clock * DASH_LEN;
50670884Sjoe			break;
50770884Sjoe		case ' ':
50870884Sjoe			sound.frequency = 0;
50970884Sjoe			sound.duration = cdot_clock * WORD_SPACE;
51070884Sjoe			break;
51170884Sjoe		default:
51270884Sjoe			sound.duration = 0;
51370884Sjoe		}
51470884Sjoe		if (sound.duration) {
51570884Sjoe			if (ioctl(spkr, SPKRTONE, &sound) == -1) {
51670884Sjoe				perror("ioctl play");
51770884Sjoe				exit(1);
51870884Sjoe			}
51970884Sjoe		}
52070884Sjoe		sound.frequency = 0;
52170884Sjoe		sound.duration = dot_clock;
52270884Sjoe		if (ioctl(spkr, SPKRTONE, &sound) == -1) {
52370884Sjoe			perror("ioctl rest");
52470884Sjoe			exit(1);
52570884Sjoe		}
52670884Sjoe	}
52770884Sjoe	sound.frequency = 0;
52870884Sjoe	sound.duration = cdot_clock * CHAR_SPACE;
52970884Sjoe	ioctl(spkr, SPKRTONE, &sound);
53070884Sjoe#endif
53170884Sjoe}
53270884Sjoe
53370884Sjoevoid
53470884Sjoettyout(const char *s)
53570884Sjoe{
53670884Sjoe	const char *c;
53770884Sjoe	int duration, on, lflags;
53893435Sluigi
53993435Sluigi	for (c = s; *c != '\0'; c++) {
54093435Sluigi		switch (*c) {
54170884Sjoe		case '.':
54270884Sjoe			on = 1;
54370884Sjoe			duration = dot_clock;
54470884Sjoe			break;
54570884Sjoe		case '-':
54670884Sjoe			on = 1;
5471722Sjkh			duration = dot_clock * DASH_LEN;
5481722Sjkh			break;
54970884Sjoe		case ' ':
5501722Sjkh			on = 0;
55170884Sjoe			duration = cdot_clock * WORD_SPACE;
5521722Sjkh			break;
5531722Sjkh		default:
5541722Sjkh			on = 0;
5551722Sjkh			duration = 0;
5561722Sjkh		}
55770884Sjoe		if (on) {
5581722Sjkh			ioctl(line, TIOCMGET, &lflags);
55970884Sjoe			lflags |= TIOCM_RTS;
56070884Sjoe			ioctl(line, TIOCMSET, &lflags);
56170884Sjoe		}
5621722Sjkh		duration *= 10000;
56370884Sjoe		if (duration)
5641722Sjkh			usleep(duration);
5651722Sjkh		ioctl(line, TIOCMGET, &lflags);
5661722Sjkh		lflags &= ~TIOCM_RTS;
5671722Sjkh		ioctl(line, TIOCMSET, &lflags);
5681722Sjkh		duration = dot_clock * 10000;
5691722Sjkh		usleep(duration);
5701722Sjkh	}
5711722Sjkh	duration = cdot_clock * CHAR_SPACE * 10000;
5721722Sjkh	usleep(duration);
5731722Sjkh}
5741722Sjkh
5751722Sjkhvoid
5761722Sjkhsighandler(int signo)
5771722Sjkh{
5781722Sjkh
5791722Sjkh	ioctl(line, TIOCMSET, &olflags);
5801722Sjkh	tcsetattr(line, TCSANOW, &otty);
5811722Sjkh
5821722Sjkh	signal(signo, SIG_DFL);
5831722Sjkh	(void)kill(getpid(), signo);
5841722Sjkh}
5851722Sjkh