morse.c revision 10352
1/* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34/* 35 * Taught to send *real* morse by Lyndon Nerenberg (VE7TCP/VE6BBM) 36 * <lyndon@orthanc.com> 37 */ 38 39#ifndef lint 40static char copyright[] = 41"@(#) Copyright (c) 1988, 1993\n\ 42 The Regents of the University of California. All rights reserved.\n"; 43#endif /* not lint */ 44 45#ifndef lint 46static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; 47#endif /* not lint */ 48 49#include <stdio.h> 50#include <ctype.h> 51#include <locale.h> 52#include <stdlib.h> 53 54#ifdef SPEAKER 55#include <machine/speaker.h> 56#include <fcntl.h> 57#endif 58 59struct morsetab { 60 char inchar; 61 char *morse; 62}; 63 64static struct morsetab mtab[] = { 65 66 /* letters */ 67 68 'a', ".-", 69 'b', "-...", 70 'c', "-.-.", 71 'd', "-..", 72 'e', ".", 73 'f', "..-.", 74 'g', "--.", 75 'h', "....", 76 'i', "..", 77 'j', ".---", 78 'k', "-.-", 79 'l', ".-..", 80 'm', "--", 81 'n', "-.", 82 'o', "---", 83 'p', ".--.", 84 'q', "--.-", 85 'r', ".-.", 86 's', "...", 87 't', "-", 88 'u', "..-", 89 'v', "...-", 90 'w', ".--", 91 'x', "-..-", 92 'y', "-.--", 93 'z', "--..", 94 95 /* digits */ 96 97 '0', "-----", 98 '1', ".----", 99 '2', "..---", 100 '3', "...--", 101 '4', "....-", 102 '5', ".....", 103 '6', "-....", 104 '7', "--...", 105 '8', "---..", 106 '9', "----.", 107 108 /* punctuation */ 109 110 ',', "--..--", 111 '.', ".-.-.-", 112 '?', "..--..", 113 '/', "-..-.", 114 '-', "-....-", 115 '=', "-...-", /* BT */ 116 ':', "---...", 117 ';', "-.-.-.", 118 '(', "-.--.", /* KN */ 119 ')', "-.--.-", 120 '$', "...-..-", 121 '+', ".-.-.", /* AR */ 122 123 /* prosigns without already assigned values */ 124 125 '#', ".-...", /* AS */ 126 '@', "...-.-", /* SK */ 127 '*', "...-.", /* VE */ 128 '%', "-...-.-", /* BK */ 129 130 '\0', "" 131}; 132 133 134static struct morsetab iso8859tab[] = { 135 '�', ".--.-", 136 '�', ".--.-", 137 '�', ".--.-", 138 '�', ".-.-", 139 '�', "-.-..", 140 '�', "..-..", 141 '�', "..-..", 142 '�', "-..-.", 143 '�', "---.", 144 '�', "..--", 145 146 '\0', "" 147}; 148 149static struct morsetab koi8rtab[] = { 150 /* 151 * the cyrillic alphabet; you'll need a KOI8R font in order 152 * to see the actual characters 153 */ 154 '�', ".-", /* a */ 155 '�', "-...", /* be */ 156 '�', ".--", /* ve */ 157 '�', "--.", /* ge */ 158 '�', "-..", /* de */ 159 '�', ".", /* ye */ 160 '�', "...-", /* she */ 161 '�', "--..", /* ze */ 162 '�', "..", /* i */ 163 '�', ".---", /* i kratkoye */ 164 '�', "-.-", /* ka */ 165 '�', ".-..", /* el */ 166 '�', "--", /* em */ 167 '�', "-.", /* en */ 168 '�', "---", /* o */ 169 '�', ".--.", /* pe */ 170 '�', ".-.", /* er */ 171 '�', "...", /* es */ 172 '�', "-", /* te */ 173 '�', "..-", /* u */ 174 '�', "..-.", /* ef */ 175 '�', "....", /* kha */ 176 '�', "-.-.", /* ce */ 177 '�', "---.", /* che */ 178 '�', "----", /* sha */ 179 '�', "--.-", /* shcha */ 180 '�', "-.--", /* yi */ 181 '�', "-..-", /* myakhkij znak */ 182 '�', "..-..", /* ae */ 183 '�', "..--", /* yu */ 184 '�', ".-.-", /* ya */ 185 186 '\0', "" 187}; 188 189void show(const char *), play(const char *), morse(char); 190 191static int pflag, sflag; 192static int wpm = 20; /* words per minute */ 193#define FREQUENCY 600 194static int freq = FREQUENCY; 195 196#ifdef SPEAKER 197#define DASH_LEN 3 198#define CHAR_SPACE 3 199#define WORD_SPACE (7 - CHAR_SPACE - 1) 200static float dot_clock; 201int spkr; 202tone_t sound; 203#endif 204 205static struct morsetab *hightab = iso8859tab; 206 207int 208main(int argc, char **argv) 209{ 210 extern char *optarg; 211 extern int optind; 212 register int ch; 213 register char *p; 214 215 while ((ch = getopt(argc, argv, "spw:f:")) != EOF) 216 switch ((char) ch) { 217 case 'f': 218 freq = atoi(optarg); 219 break; 220 case 'p': 221 pflag = 1; 222 break; 223 case 's': 224 sflag = 1; 225 break; 226 case 'w': 227 wpm = atoi(optarg); 228 break; 229 case '?': 230 default: 231 fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr); 232 exit(1); 233 } 234 if (pflag && sflag) { 235 fputs("morse: only one of -p and -s allowed\n", stderr); 236 exit(1); 237 } 238 if (pflag && ((wpm < 1) || (wpm > 60))) { 239 fputs("morse: insane speed\n", stderr); 240 exit(1); 241 } 242 if (pflag && (freq == 0)) 243 freq = FREQUENCY; 244 245 (void)setuid(getuid()); 246#ifdef SPEAKER 247 if (pflag) { 248 if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 249 perror(SPEAKER); 250 exit(1); 251 } 252 dot_clock = wpm / 2.4; /* dots/sec */ 253 dot_clock = 1 / dot_clock; /* duration of a dot */ 254 dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 255 /* the dot rate */ 256 dot_clock = dot_clock * 100; /* scale for ioctl */ 257 } 258#endif 259 argc -= optind; 260 argv += optind; 261 262 if((p = getenv("LC_CTYPE")) || (p = getenv("LANG"))) { 263 if(strlen(p) >= strlen("KOI8-R") && 264 strcasecmp(&p[strlen(p) - strlen("KOI8-R")], "KOI8-R") == 0) 265 hightab = koi8rtab; 266 setlocale(LC_CTYPE, p); 267 } else { 268 setlocale(LC_CTYPE, ""); 269 } 270 271 if (*argv) { 272 do { 273 for (p = *argv; *p; ++p) { 274 morse((int) *p); 275 } 276 morse((int) ' '); 277 } while (*++argv); 278 } else { 279 while ((ch = getchar()) != EOF) 280 morse(ch); 281 } 282 exit(0); 283} 284 285void 286morse(char c) 287{ 288 struct morsetab *m; 289 290 if (isalpha(c)) 291 c = tolower(c); 292 if ((c == '\r') || (c == '\n')) 293 c = ' '; 294 if (c == ' ') { 295 if (pflag) { 296 play(" "); 297 return; 298 } else { 299 show(""); 300 return; 301 } 302 } 303 for (m = ((unsigned char)c < 0x80? mtab: hightab); 304 m->inchar != '\0'; 305 m++) { 306 if (m->inchar == c) { 307 if (pflag) { 308 play(m->morse); 309 } else 310 show(m->morse); 311 } 312 } 313} 314 315void 316show(const char *s) 317{ 318 if (sflag) 319 printf(" %s", s); 320 else 321 for (; *s; ++s) 322 printf(" %s", *s == '.' ? "dit" : "dah"); 323 printf("\n"); 324} 325 326void 327play(const char *s) 328{ 329#ifdef SPEAKER 330 const char *c; 331 332 for (c = s; *c != '\0'; c++) { 333 switch ((int) *c) { 334 case '.': 335 sound.frequency = freq; 336 sound.duration = dot_clock; 337 break; 338 case '-': 339 sound.frequency = freq; 340 sound.duration = dot_clock * DASH_LEN; 341 break; 342 case ' ': 343 sound.frequency = 0; 344 sound.duration = dot_clock * WORD_SPACE; 345 break; 346 default: 347 sound.duration = 0; 348 } 349 if (sound.duration) { 350 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 351 perror("ioctl play"); 352 exit(1); 353 } 354 } 355 sound.frequency = 0; 356 sound.duration = dot_clock; 357 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 358 perror("ioctl rest"); 359 exit(1); 360 } 361 } 362 sound.frequency = 0; 363 sound.duration = dot_clock * CHAR_SPACE; 364 ioctl(spkr, SPKRTONE, &sound); 365#endif 366} 367