Index: head/usr.bin/morse/morse.6 =================================================================== --- head/usr.bin/morse/morse.6 (revision 327613) +++ head/usr.bin/morse/morse.6 (revision 327614) @@ -1,197 +1,202 @@ .\" Copyright (c) 2000 Alexey Zelkin. All rights reserved. .\" Copyright (c) 1988, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)bcd.6 8.1 (Berkeley) 5/31/93 .\" $FreeBSD$ .\" .Dd June 7, 2005 .Dt MORSE 6 .Os .Sh NAME .Nm morse .Nd reformat input as morse code .Sh SYNOPSIS .Nm .Op Fl elps .Op Fl d Ar device .Op Fl w Ar speed .Op Fl c Ar speed .Op Fl f Ar frequency .Op Ar string ... .Sh DESCRIPTION The .Nm command reads the given input and reformats it in the form of morse code. Acceptable input are command line arguments or the standard input. .Pp Available options: .Bl -tag -width indent .It Fl l The .Fl l option produces output suitable for .Xr led 4 devices. .It Fl s The .Fl s option produces dots and dashes rather than words. .It Fl p Send morse the real way. This only works if your system has .Xr speaker 4 support. .It Fl w Ar speed Set the sending speed in words per minute. If not specified, the default speed of 20 WPM is used. .It Fl c Ar speed Farnsworth support. Set the spacing between characters in words per minute. This is independent of the speed that the individual characters are sent. If not specified, defaults to the effective value of the .Fl w option. .It Fl f Ar frequency Set the sidetone frequency to something other than the default 600 Hz. .It Fl d Ar device Similar to .Fl p , but use the RTS line of .Ar device (which must be a TTY device) in order to emit the morse code. .It Fl e Echo each character before it is sent, used together with either .Fl p or .Fl d . +.It Fl D +Decode morse output consisting of dots and dashes (as generated by using +the +.Fl s +option). .El .Pp The .Fl w , c and .Fl f flags only work in conjunction with either the .Fl p or the .Fl d flag. .Pp Not all prosigns have corresponding characters. Use .Ql # for .Em AS , .Ql & for .Em SK , .Ql * for .Em VE and .Ql % for .Em BK . The more common prosigns are .Ql = for .Em BT , .Ql \&( for .Em KN and .Ql + for .Em AR . .Pp Using the .Fl d flag, it is possible to key an external device, like a sidetone generator with a headset for training purposes, or even your ham radio transceiver. For the latter, simply connect an NPN transistor to the serial port .Ar device , emitter connected to ground, base connected through a resistor (few kiloohms) to RTS, collector to the key line of your transceiver (assuming the transceiver has a positive key supply voltage and is keyed by grounding the key input line). A capacitor (some nanofarads) between base and ground is advisable to keep stray RF away, and to suppress the minor glitch that is generated during program startup. .Sh ENVIRONMENT Your .Ev LC_CTYPE locale codeset determines how characters with the high-order bit set are interpreted. .Pp .Bl -tag -width ".Li ISO8859-15" -compact .It Li ISO8859-1 .It Li ISO8859-15 Interpret characters with the high-order bit set as Western European characters. .Pp .It Li KOI8-R Interpret characters with the high-order bit set as Cyrillic characters. .Pp .It Li ISO8859-7 Interpret characters with the high-order bit set as Greek characters. .El .Sh FILES .Bl -tag -width ".Pa /dev/speaker" -compact .It Pa /dev/speaker .Xr speaker 4 device file .El .Sh SEE ALSO .Xr speaker 4 .Sh HISTORY Sound support for .Nm added by .An Lyndon Nerenberg (VE6BBM) Aq Mt lyndon@orthanc.ca . .Pp Ability to key an external device added by .An J\(:org Wunsch (DL8DTL). .Pp Farnsworth support for .Nm added by .An Stephen Cravey (N5UUU). .Sh BUGS Only understands a few European characters (German and French), no Asian characters, and no continental landline code. .Pp Sends a bit slower than it should due to system overhead. Some people would call this a feature. Index: head/usr.bin/morse/morse.c =================================================================== --- head/usr.bin/morse/morse.c (revision 327613) +++ head/usr.bin/morse/morse.c (revision 327614) @@ -1,589 +1,670 @@ /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Taught to send *real* morse by Lyndon Nerenberg (VE6BBM) * */ static const char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #if 0 static char sccsid[] = "@(#)morse.c 8.1 (Berkeley) 5/31/93"; #endif static const char rcsid[] = "$FreeBSD$"; #include #include #include +#include #include #include #include #include #include #include #include #include #include /* Always use the speaker, let the open fail if -p is selected */ #define SPEAKER "/dev/speaker" +#define WHITESPACE " \t\n" +#define DELIMITERS " \t" + #ifdef SPEAKER #include #endif struct morsetab { const char inchar; const char *morse; }; static const struct morsetab mtab[] = { /* letters */ {'a', ".-"}, {'b', "-..."}, {'c', "-.-."}, {'d', "-.."}, {'e', "."}, {'f', "..-."}, {'g', "--."}, {'h', "...."}, {'i', ".."}, {'j', ".---"}, {'k', "-.-"}, {'l', ".-.."}, {'m', "--"}, {'n', "-."}, {'o', "---"}, {'p', ".--."}, {'q', "--.-"}, {'r', ".-."}, {'s', "..."}, {'t', "-"}, {'u', "..-"}, {'v', "...-"}, {'w', ".--"}, {'x', "-..-"}, {'y', "-.--"}, {'z', "--.."}, /* digits */ {'0', "-----"}, {'1', ".----"}, {'2', "..---"}, {'3', "...--"}, {'4', "....-"}, {'5', "....."}, {'6', "-...."}, {'7', "--..."}, {'8', "---.."}, {'9', "----."}, /* punctuation */ {',', "--..--"}, {'.', ".-.-.-"}, {'"', ".-..-."}, {'!', "..--."}, {'?', "..--.."}, {'/', "-..-."}, {'-', "-....-"}, {'=', "-...-"}, /* BT */ {':', "---..."}, {';', "-.-.-."}, {'(', "-.--."}, /* KN */ {')', "-.--.-"}, {'$', "...-..-"}, {'+', ".-.-."}, /* AR */ {'@', ".--.-."}, /* AC */ {'_', "..--.-"}, {'\'', ".----."}, /* prosigns without already assigned values */ {'#', ".-..."}, /* AS */ {'&', "...-.-"}, /* SK */ {'*', "...-."}, /* VE */ {'%', "-...-.-"}, /* BK */ {'\0', ""} }; /* * Code-points for some Latin1 chars in ISO-8859-1 encoding. * UTF-8 encoded chars in the comments. */ static const struct morsetab iso8859_1tab[] = { {'\340', ".--.-"}, /* à */ {'\341', ".--.-"}, /* á */ {'\342', ".--.-"}, /* â */ {'\344', ".-.-"}, /* ä */ {'\347', "-.-.."}, /* ç */ {'\350', "..-.."}, /* è */ {'\351', "..-.."}, /* é */ {'\352', "-..-."}, /* ê */ {'\361', "--.--"}, /* ñ */ {'\366', "---."}, /* ö */ {'\374', "..--"}, /* ü */ {'\0', ""} }; /* * Code-points for some Greek chars in ISO-8859-7 encoding. * UTF-8 encoded chars in the comments. */ static const struct morsetab iso8859_7tab[] = { /* * This table does not implement: * - the special sequences for the seven diphthongs, * - the punctuation differences. * Implementing these features would introduce too many * special-cases in the program's main loop. * The diphthong sequences are: * alpha iota .-.- * alpha upsilon ..-- * epsilon upsilon ---. * eta upsilon ...- * omicron iota ---.. * omicron upsilon ..- * upsilon iota .--- * The different punctuation symbols are: * ; ..-.- * ! --..-- */ {'\341', ".-"}, /* α, alpha */ {'\334', ".-"}, /* ά, alpha with acute */ {'\342', "-..."}, /* β, beta */ {'\343', "--."}, /* γ, gamma */ {'\344', "-.."}, /* δ, delta */ {'\345', "."}, /* ε, epsilon */ {'\335', "."}, /* έ, epsilon with acute */ {'\346', "--.."}, /* ζ, zeta */ {'\347', "...."}, /* η, eta */ {'\336', "...."}, /* ή, eta with acute */ {'\350', "-.-."}, /* θ, theta */ {'\351', ".."}, /* ι, iota */ {'\337', ".."}, /* ί, iota with acute */ {'\372', ".."}, /* ϊ, iota with diaeresis */ {'\300', ".."}, /* ΐ, iota with acute and diaeresis */ {'\352', "-.-"}, /* κ, kappa */ {'\353', ".-.."}, /* λ, lambda */ {'\354', "--"}, /* μ, mu */ {'\355', "-."}, /* ν, nu */ {'\356', "-..-"}, /* ξ, xi */ {'\357', "---"}, /* ο, omicron */ {'\374', "---"}, /* ό, omicron with acute */ {'\360', ".--."}, /* π, pi */ {'\361', ".-."}, /* ρ, rho */ {'\363', "..."}, /* σ, sigma */ {'\362', "..."}, /* ς, final sigma */ {'\364', "-"}, /* τ, tau */ {'\365', "-.--"}, /* υ, upsilon */ {'\375', "-.--"}, /* ύ, upsilon with acute */ {'\373', "-.--"}, /* ϋ, upsilon and diaeresis */ {'\340', "-.--"}, /* ΰ, upsilon with acute and diaeresis */ {'\366', "..-."}, /* φ, phi */ {'\367', "----"}, /* χ, chi */ {'\370', "--.-"}, /* ψ, psi */ {'\371', ".--"}, /* ω, omega */ {'\376', ".--"}, /* ώ, omega with acute */ {'\0', ""} }; /* * Code-points for the Cyrillic alphabet in KOI8-R encoding. * UTF-8 encoded chars in the comments. */ static const struct morsetab koi8rtab[] = { {'\301', ".-"}, /* а, a */ {'\302', "-..."}, /* б, be */ {'\327', ".--"}, /* в, ve */ {'\307', "--."}, /* г, ge */ {'\304', "-.."}, /* д, de */ {'\305', "."}, /* е, ye */ {'\243', "."}, /* ё, yo, the same as ye */ {'\326', "...-"}, /* ж, she */ {'\332', "--.."}, /* з, ze */ {'\311', ".."}, /* и, i */ {'\312', ".---"}, /* й, i kratkoye */ {'\313', "-.-"}, /* к, ka */ {'\314', ".-.."}, /* л, el */ {'\315', "--"}, /* м, em */ {'\316', "-."}, /* н, en */ {'\317', "---"}, /* о, o */ {'\320', ".--."}, /* п, pe */ {'\322', ".-."}, /* р, er */ {'\323', "..."}, /* с, es */ {'\324', "-"}, /* т, te */ {'\325', "..-"}, /* у, u */ {'\306', "..-."}, /* ф, ef */ {'\310', "...."}, /* х, kha */ {'\303', "-.-."}, /* ц, ce */ {'\336', "---."}, /* ч, che */ {'\333', "----"}, /* ш, sha */ {'\335', "--.-"}, /* щ, shcha */ {'\331', "-.--"}, /* ы, yi */ {'\330', "-..-"}, /* ь, myakhkij znak */ {'\334', "..-.."}, /* э, ae */ {'\300', "..--"}, /* ю, yu */ {'\321', ".-.-"}, /* я, ya */ {'\0', ""} }; static void show(const char *), play(const char *), morse(char); +static void decode (char *), fdecode(FILE *); static void ttyout(const char *); static void sighandler(int); -#define GETOPTOPTS "c:d:ef:lsw:" -#define USAGE \ -"usage: morse [-els] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n" - -static int pflag, lflag, sflag, eflag; +static int pflag, lflag, rflag, sflag, eflag; static int wpm = 20; /* effective words per minute */ static int cpm; /* effective words per minute between * characters */ #define FREQUENCY 600 static int freq = FREQUENCY; static char *device; /* for tty-controlled generator */ #define DASH_LEN 3 #define CHAR_SPACE 3 #define WORD_SPACE (7 - CHAR_SPACE - 1) static float dot_clock; static float cdot_clock; static int spkr, line; static struct termios otty, ntty; static int olflags; #ifdef SPEAKER static tone_t sound; -#undef GETOPTOPTS -#define GETOPTOPTS "c:d:ef:lpsw:" -#undef USAGE +#define GETOPTOPTS "c:d:ef:lprsw:" #define USAGE \ -"usage: morse [-elps] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n" +"usage: morse [-elprs] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n" +#else +#define GETOPTOPTS "c:d:ef:lrsw:" +#define USAGE \ +"usage: morse [-elrs] [-d device] [-w speed] [-c speed] [-f frequency] [string ...]\n" + #endif static const struct morsetab *hightab; int main(int argc, char **argv) { int ch, lflags; char *p, *codeset; while ((ch = getopt(argc, argv, GETOPTOPTS)) != -1) switch ((char) ch) { case 'c': cpm = atoi(optarg); break; case 'd': device = optarg; break; case 'e': eflag = 1; setvbuf(stdout, 0, _IONBF, 0); break; case 'f': freq = atoi(optarg); break; case 'l': lflag = 1; break; #ifdef SPEAKER case 'p': pflag = 1; break; #endif + case 'r': + rflag = 1; + break; case 's': sflag = 1; break; case 'w': wpm = atoi(optarg); break; case '?': default: - fputs(USAGE, stderr); - exit(1); + errx(1, USAGE); } - if (sflag && lflag) { - fputs("morse: only one of -l and -s allowed\n", stderr); - exit(1); + if ((sflag && lflag) || (sflag && rflag) || (lflag && rflag)) { + errx(1, "morse: only one of -l, -s, and -r allowed\n"); } if ((pflag || device) && (sflag || lflag)) { - fputs("morse: only one of -p, -d and -l, -s allowed\n", stderr); - exit(1); + errx(1, "morse: only one of -p, -d and -l, -s allowed\n"); } - if (cpm == 0) + if (cpm == 0) { cpm = wpm; + } if ((pflag || device) && ((wpm < 1) || (wpm > 60) || (cpm < 1) || (cpm > 60))) { - fputs("morse: insane speed\n", stderr); - exit(1); + errx(1, "morse: insane speed\n"); } - if ((pflag || device) && (freq == 0)) + if ((pflag || device) && (freq == 0)) { freq = FREQUENCY; - + } #ifdef SPEAKER if (pflag) { if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { - perror(SPEAKER); - exit(1); + err(1, SPEAKER); } } else #endif if (device) { if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) { - perror("open tty line"); - exit(1); + err(1, "open tty line"); } if (tcgetattr(line, &otty) == -1) { - perror("tcgetattr() failed"); - exit(1); + err(1, "tcgetattr() failed"); } ntty = otty; ntty.c_cflag |= CLOCAL; tcsetattr(line, TCSANOW, &ntty); lflags = fcntl(line, F_GETFL); lflags &= ~O_NONBLOCK; fcntl(line, F_SETFL, &lflags); ioctl(line, TIOCMGET, &lflags); lflags &= ~TIOCM_RTS; olflags = lflags; ioctl(line, TIOCMSET, &lflags); (void)signal(SIGHUP, sighandler); (void)signal(SIGINT, sighandler); (void)signal(SIGQUIT, sighandler); (void)signal(SIGTERM, sighandler); } if (pflag || device) { dot_clock = wpm / 2.4; /* dots/sec */ dot_clock = 1 / dot_clock; /* duration of a dot */ dot_clock = dot_clock / 2; /* dot_clock runs at twice */ /* the dot rate */ dot_clock = dot_clock * 100; /* scale for ioctl */ cdot_clock = cpm / 2.4; /* dots/sec */ cdot_clock = 1 / cdot_clock; /* duration of a dot */ cdot_clock = cdot_clock / 2; /* dot_clock runs at twice */ /* the dot rate */ cdot_clock = cdot_clock * 100; /* scale for ioctl */ } argc -= optind; argv += optind; if (setlocale(LC_CTYPE, "") != NULL && *(codeset = nl_langinfo(CODESET)) != '\0') { if (strcmp(codeset, "KOI8-R") == 0) hightab = koi8rtab; else if (strcmp(codeset, "ISO8859-1") == 0 || strcmp(codeset, "ISO8859-15") == 0) hightab = iso8859_1tab; else if (strcmp(codeset, "ISO8859-7") == 0) hightab = iso8859_7tab; } - if (lflag) + if (lflag) { printf("m"); - if (*argv) { + } + if (rflag) { + if (*argv) { + do { + p = strtok(*argv, DELIMITERS); + if (p == NULL) { + decode(*argv); + } + else { + while (p) { + decode(p); + p = strtok(NULL, DELIMITERS); + } + } + } while (*++argv); + putchar('\n'); + } else { + fdecode(stdin); + } + } + else if (*argv) { do { for (p = *argv; *p; ++p) { if (eflag) putchar(*p); morse(*p); } if (eflag) putchar(' '); morse(' '); } while (*++argv); } else { while ((ch = getchar()) != EOF) { if (eflag) putchar(ch); morse(ch); } } if (device) tcsetattr(line, TCSANOW, &otty); exit(0); } static void morse(char c) { const struct morsetab *m; if (isalpha((unsigned char)c)) c = tolower((unsigned char)c); if ((c == '\r') || (c == '\n')) c = ' '; if (c == ' ') { if (pflag) play(" "); else if (device) ttyout(" "); else if (lflag) printf("\n"); else show(""); return; } for (m = ((unsigned char)c < 0x80? mtab: hightab); m != NULL && m->inchar != '\0'; m++) { if (m->inchar == c) { if (pflag) { play(m->morse); } else if (device) { ttyout(m->morse); } else show(m->morse); } } } static void show(const char *s) { if (lflag) { printf("%s ", s); } else if (sflag) { printf(" %s\n", s); } else { for (; *s; ++s) printf(" %s", *s == '.' ? *(s + 1) == '\0' ? "dit" : "di" : "dah"); printf("\n"); } } static void play(const char *s) { #ifdef SPEAKER const char *c; for (c = s; *c != '\0'; c++) { switch (*c) { case '.': sound.frequency = freq; sound.duration = dot_clock; break; case '-': sound.frequency = freq; sound.duration = dot_clock * DASH_LEN; break; case ' ': sound.frequency = 0; sound.duration = cdot_clock * WORD_SPACE; break; default: sound.duration = 0; } if (sound.duration) { if (ioctl(spkr, SPKRTONE, &sound) == -1) { - perror("ioctl play"); - exit(1); + err(1, "ioctl play"); } } sound.frequency = 0; sound.duration = dot_clock; if (ioctl(spkr, SPKRTONE, &sound) == -1) { - perror("ioctl rest"); - exit(1); + err(1, "ioctl rest"); } } sound.frequency = 0; sound.duration = cdot_clock * CHAR_SPACE; ioctl(spkr, SPKRTONE, &sound); #endif } static void ttyout(const char *s) { const char *c; int duration, on, lflags; for (c = s; *c != '\0'; c++) { switch (*c) { case '.': on = 1; duration = dot_clock; break; case '-': on = 1; duration = dot_clock * DASH_LEN; break; case ' ': on = 0; duration = cdot_clock * WORD_SPACE; break; default: on = 0; duration = 0; } if (on) { ioctl(line, TIOCMGET, &lflags); lflags |= TIOCM_RTS; ioctl(line, TIOCMSET, &lflags); } duration *= 10000; if (duration) usleep(duration); ioctl(line, TIOCMGET, &lflags); lflags &= ~TIOCM_RTS; ioctl(line, TIOCMSET, &lflags); duration = dot_clock * 10000; usleep(duration); } duration = cdot_clock * CHAR_SPACE * 10000; usleep(duration); +} + +void +fdecode(FILE *stream) +{ + char *n, *p, *s; + char buf[BUFSIZ]; + + s = buf; + while (fgets(s, BUFSIZ - (s - buf), stdin)) { + p = buf; + + while (*p && isblank(*p)) { + p++; + } + while (*p && isspace(*p)) { + p++; + putchar (' '); + } + while (*p) { + n = strpbrk(p, WHITESPACE); + if (n == NULL) { + /* The token was interrupted at the end + * of the buffer. Shift it to the begin + * of the buffer. + */ + for (s = buf; *p; *s++ = *p++) + ; + } else { + *n = '\0'; + n++; + decode(p); + p = n; + } + } + } + putchar('\n'); +} + +void +decode(char *p) +{ + char c; + const struct morsetab *m; + + c = ' '; + for (m = mtab; m != NULL && m->inchar != '\0'; m++) { + if (strcmp(m->morse, p) == 0) { + c = m->inchar; + break; + } + } + + if (c == ' ') + for (m = hightab; m != NULL && m->inchar != '\0'; m++) { + if (strcmp(m->morse, p) == 0) { + c = m->inchar; + break; + } + } + + putchar(c); } static void sighandler(int signo) { ioctl(line, TIOCMSET, &olflags); tcsetattr(line, TCSANOW, &otty); signal(signo, SIG_DFL); (void)kill(getpid(), signo); }