morse.c revision 28979
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 /* revoke */ 216 setegid(getgid()); 217 setgid(getgid()); 218 219 while ((ch = getopt(argc, argv, "spw:f:")) != EOF) 220 switch ((char) ch) { 221 case 'f': 222 freq = atoi(optarg); 223 break; 224 case 'p': 225 pflag = 1; 226 break; 227 case 's': 228 sflag = 1; 229 break; 230 case 'w': 231 wpm = atoi(optarg); 232 break; 233 case '?': 234 default: 235 fputs("usage: morse [-s] [-p] [-w speed] [-f frequency] [string ...]\n", stderr); 236 exit(1); 237 } 238 if (pflag && sflag) { 239 fputs("morse: only one of -p and -s allowed\n", stderr); 240 exit(1); 241 } 242 if (pflag && ((wpm < 1) || (wpm > 60))) { 243 fputs("morse: insane speed\n", stderr); 244 exit(1); 245 } 246 if (pflag && (freq == 0)) 247 freq = FREQUENCY; 248 249 (void)setuid(getuid()); 250#ifdef SPEAKER 251 if (pflag) { 252 if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { 253 perror(SPEAKER); 254 exit(1); 255 } 256 dot_clock = wpm / 2.4; /* dots/sec */ 257 dot_clock = 1 / dot_clock; /* duration of a dot */ 258 dot_clock = dot_clock / 2; /* dot_clock runs at twice */ 259 /* the dot rate */ 260 dot_clock = dot_clock * 100; /* scale for ioctl */ 261 } 262#endif 263 argc -= optind; 264 argv += optind; 265 266 if((p = getenv("LC_CTYPE")) || (p = getenv("LANG"))) { 267 if(strlen(p) >= strlen("KOI8-R") && 268 strcasecmp(&p[strlen(p) - strlen("KOI8-R")], "KOI8-R") == 0) 269 hightab = koi8rtab; 270 setlocale(LC_CTYPE, p); 271 } else { 272 setlocale(LC_CTYPE, ""); 273 } 274 275 if (*argv) { 276 do { 277 for (p = *argv; *p; ++p) { 278 morse((int) *p); 279 } 280 morse((int) ' '); 281 } while (*++argv); 282 } else { 283 while ((ch = getchar()) != EOF) 284 morse(ch); 285 } 286 exit(0); 287} 288 289void 290morse(char c) 291{ 292 struct morsetab *m; 293 294 if (isalpha(c)) 295 c = tolower(c); 296 if ((c == '\r') || (c == '\n')) 297 c = ' '; 298 if (c == ' ') { 299 if (pflag) { 300 play(" "); 301 return; 302 } else { 303 show(""); 304 return; 305 } 306 } 307 for (m = ((unsigned char)c < 0x80? mtab: hightab); 308 m->inchar != '\0'; 309 m++) { 310 if (m->inchar == c) { 311 if (pflag) { 312 play(m->morse); 313 } else 314 show(m->morse); 315 } 316 } 317} 318 319void 320show(const char *s) 321{ 322 if (sflag) 323 printf(" %s", s); 324 else 325 for (; *s; ++s) 326 printf(" %s", *s == '.' ? "dit" : "dah"); 327 printf("\n"); 328} 329 330void 331play(const char *s) 332{ 333#ifdef SPEAKER 334 const char *c; 335 336 for (c = s; *c != '\0'; c++) { 337 switch ((int) *c) { 338 case '.': 339 sound.frequency = freq; 340 sound.duration = dot_clock; 341 break; 342 case '-': 343 sound.frequency = freq; 344 sound.duration = dot_clock * DASH_LEN; 345 break; 346 case ' ': 347 sound.frequency = 0; 348 sound.duration = dot_clock * WORD_SPACE; 349 break; 350 default: 351 sound.duration = 0; 352 } 353 if (sound.duration) { 354 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 355 perror("ioctl play"); 356 exit(1); 357 } 358 } 359 sound.frequency = 0; 360 sound.duration = dot_clock; 361 if (ioctl(spkr, SPKRTONE, &sound) == -1) { 362 perror("ioctl rest"); 363 exit(1); 364 } 365 } 366 sound.frequency = 0; 367 sound.duration = dot_clock * CHAR_SPACE; 368 ioctl(spkr, SPKRTONE, &sound); 369#endif 370} 371