morse.c revision 1.23 1 /* $NetBSD: morse.c,v 1.23 2024/10/12 19:26:24 rillig Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
34 The Regents of the University of California. All rights reserved.");
35 /* @(#)morse.c 8.1 (Berkeley) 5/31/93 */
36 __RCSID("$NetBSD: morse.c,v 1.23 2024/10/12 19:26:24 rillig Exp $");
37
38 #include <ctype.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 static const char digit[][6] = {
45 "-----",
46 ".----",
47 "..---",
48 "...--",
49 "....-",
50 ".....",
51 "-....",
52 "--...",
53 "---..",
54 "----.",
55 };
56
57 static const char alph[][5] = {
58 ".-",
59 "-...",
60 "-.-.",
61 "-..",
62 ".",
63 "..-.",
64 "--.",
65 "....",
66 "..",
67 ".---",
68 "-.-",
69 ".-..",
70 "--",
71 "-.",
72 "---",
73 ".--.",
74 "--.-",
75 ".-.",
76 "...",
77 "-",
78 "..-",
79 "...-",
80 ".--",
81 "-..-",
82 "-.--",
83 "--..",
84 };
85
86 static const struct {
87 char c;
88 const char morse[7];
89 } other[] = {
90 { '.', ".-.-.-" },
91 { ',', "--..--" },
92 { ':', "---..." },
93 { '?', "..--.." },
94 { '\'', ".----." },
95 { '-', "-....-" },
96 { '/', "-..-." },
97 { '(', "-.--." },
98 { ')', "-.--.-" },
99 { '"', ".-..-." },
100 { '=', "-...-" },
101 { '+', ".-.-." },
102 { '_', "..--.-" },
103 { '@', ".--.-." },
104 { '\0', "" }
105 };
106
107 static void morse(int);
108 static void decode(const char *);
109 static void show(const char *);
110
111 static int sflag;
112 static int dflag;
113
114 int
115 main(int argc, char **argv)
116 {
117 int ch;
118 char *p;
119
120 /* Revoke setgid privileges */
121 setgid(getgid());
122
123 while ((ch = getopt(argc, argv, "ds")) != -1)
124 switch ((char)ch) {
125 case 'd':
126 dflag = 1;
127 break;
128 case 's':
129 sflag = 1;
130 break;
131 default:
132 fprintf(stderr, "usage: morse [-ds] [string ...]\n");
133 exit(1);
134 }
135 argc -= optind;
136 argv += optind;
137
138 if (dflag) {
139 if (*argv) {
140 do {
141 decode(*argv);
142 } while (*++argv);
143 } else {
144 char foo[10]; /* All morse chars shorter than this */
145 int is_blank, i;
146
147 i = 0;
148 is_blank = 0;
149 while ((ch = getchar()) != EOF) {
150 if (ch == '-' || ch == '.') {
151 foo[i++] = ch;
152 if (i == 10) {
153 /* overrun means gibberish--print 'x' and
154 * advance */
155 i = 0;
156 putchar('x');
157 while ((ch = getchar()) != EOF &&
158 (ch == '.' || ch == '-'))
159 ;
160 is_blank = 1;
161 }
162 } else if (i) {
163 foo[i] = '\0';
164 decode(foo);
165 i = 0;
166 is_blank = 0;
167 } else if (isspace(ch)) {
168 if (is_blank) {
169 /* print whitespace for each double blank */
170 putchar(' ');
171 is_blank = 0;
172 } else
173 is_blank = 1;
174 }
175 }
176 }
177 putchar('\n');
178 } else {
179 if (*argv)
180 do {
181 for (p = *argv; *p; ++p)
182 morse((unsigned char)*p);
183 show("");
184 } while (*++argv);
185 else while ((ch = getchar()) != EOF)
186 morse(ch);
187 show("...-.-"); /* SK */
188 }
189
190 return 0;
191 }
192
193 void
194 decode(const char *s)
195 {
196 for (size_t i = 0; i < __arraycount(digit); i++)
197 if (strcmp(digit[i], s) == 0) {
198 putchar('0' + i);
199 return;
200 }
201
202 for (size_t i = 0; i < __arraycount(alph); i++)
203 if (strcmp(alph[i], s) == 0) {
204 putchar('A' + i);
205 return;
206 }
207
208 for (size_t i = 0; other[i].c; i++)
209 if (strcmp(other[i].morse, s) == 0) {
210 putchar(other[i].c);
211 return;
212 }
213
214 if (strcmp("...-.-", s) == 0) /* SK */
215 return;
216
217 putchar('x'); /* line noise */
218 }
219
220 void
221 morse(int c)
222 {
223 if (isalpha(c))
224 show(alph[c - (isupper(c) ? 'A' : 'a')]);
225 else if (isdigit(c))
226 show(digit[c - '0']);
227 else if (isspace(c))
228 show(""); /* could show BT for a pause */
229 else
230 for (int i = 0; other[i].c; i++)
231 if (other[i].c == c) {
232 show(other[i].morse);
233 break;
234 }
235 }
236
237 void
238 show(const char *s)
239 {
240 if (sflag)
241 printf(" %s", s);
242 else for (; *s; ++s)
243 printf(" %s", *s == '.' ? "dit" : "daw");
244 printf("\n");
245 }
246