From b091b880f963b5181ac09a202bff4e41a38dfbe0 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 1 Mar 2010 10:45:47 +0100 Subject: [PATCH] ldattach: add --iflag command line option Add a command line option '-i' / '--iflag' for setting or clearing input flags on the serial device before attaching the line discipline. [kzak@redhat.com: - use generic functions for work with iflags table - add list of iflags to usage/help output - move iflags parsing to separate function] Impact: added functionality Signed-off-by: Tilman Schmidt Signed-off-by: Karel Zak --- sys-utils/ldattach.8 | 11 +++++++- sys-utils/ldattach.c | 61 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/sys-utils/ldattach.8 b/sys-utils/ldattach.8 index 3856999f0..f78ab34cb 100644 --- a/sys-utils/ldattach.8 +++ b/sys-utils/ldattach.8 @@ -1,6 +1,6 @@ .\" Copyright 2008 Tilman Schmidt (tilman@imap.cc) .\" May be distributed under the GNU General Public License version 2 or later -.TH LDATTACH 8 "14 January 2008" "Linux 2.6" "Linux Programmer's Manual" +.TH LDATTACH 8 "14 February 2010" "Linux 2.6" "Linux Programmer's Manual" .SH NAME ldattach \- attach a line discipline to a serial line .SH SYNOPSIS @@ -8,6 +8,8 @@ ldattach \- attach a line discipline to a serial line .RB [ \-dhV78neo12 ] .RB [ \-s .IR speed ] +.RB [ \-i +.IR iflag ] .I ldisc device .SH DESCRIPTION The @@ -122,6 +124,13 @@ Sets the number of stop bits of the serial line to one. .TP \fB-2\fP | \fB--twostopbits\fP Sets the number of stop bits of the serial line to two. +.TP +\fB-i\fP \fIvalue\fP | \fB--iflag\fP [\fB-\fP]\fIvalue\fP{,...} +Sets the specified bits in the c_iflag word of the serial line. +\fIValue\fP may be a number or a symbolic name. +If \fIvalue\fP is prefixed by a minus sign, clear the specified bits instead. +Several comma separated \fIvalue\fPs may be given in order to +set and clear multiple bits. .SH "SEE ALSO" .BR inputattach (1), .BR ttys (4) diff --git a/sys-utils/ldattach.c b/sys-utils/ldattach.c index e85677c89..26cf10a70 100644 --- a/sys-utils/ldattach.c +++ b/sys-utils/ldattach.c @@ -76,6 +76,27 @@ static const struct ld_table ld_discs[] = { NULL, 0 } }; +/* known c_iflag names */ +static const struct ld_table ld_iflags[] = +{ + { "IGNBRK", IGNBRK }, + { "BRKINT", BRKINT }, + { "IGNPAR", IGNPAR }, + { "PARMRK", PARMRK }, + { "INPCK", INPCK }, + { "ISTRIP", ISTRIP }, + { "INLCR", INLCR }, + { "IGNCR", IGNCR }, + { "ICRNL", ICRNL }, + { "IUCLC", IUCLC }, + { "IXON", IXON }, + { "IXANY", IXANY }, + { "IXOFF", IXOFF }, + { "IMAXBEL", IMAXBEL }, + { "IUTF8", IUTF8 }, + { NULL, 0 } +}; + static int lookup_table(const struct ld_table *tab, const char *str) { const struct ld_table *t; @@ -98,14 +119,39 @@ static void print_table(FILE *out, const struct ld_table *tab) } } +static int parse_iflag(char *str, int *set_iflag, int *clr_iflag) +{ + int iflag; + char *s, *end; + + for (s = strtok(str, ","); s != NULL; s = strtok(NULL, ",")) { + if (*s == '-') + s++; + if ((iflag = lookup_table(ld_iflags, s)) < 0) { + iflag = strtol(s, &end, 0); + if (*end || iflag < 0) + errx(EXIT_FAILURE, _("invalid iflag: %s"), s); + } + if (s > str && *(s - 1) == '-') + *clr_iflag |= iflag; + else + *set_iflag |= iflag; + } + + dbg("iflag (set/clear): %d/%d", *set_iflag, *clr_iflag); + return 0; +} + + static void __attribute__((__noreturn__)) usage(int exitcode) { fprintf(stderr, - _("\nUsage: %s [ -dhV78neo12 ] [ -s ] \n"), + _("\nUsage: %s [ -dhV78neo12 ] [ -s ] [ -i [-] ] \n"), progname); fputs(_("\nKnown names:\n"), stderr); print_table(stderr, ld_discs); - + fputs(_("\nKnown names:\n"), stderr); + print_table(stderr, ld_iflags); exit(exitcode); } @@ -138,6 +184,7 @@ int main(int argc, char **argv) int tty_fd; struct termios ts; int speed = 0, bits = '-', parity = '-', stop = '-'; + int set_iflag = 0, clr_iflag = 0; int ldisc; int optc; char *end; @@ -151,6 +198,7 @@ int main(int argc, char **argv) {"oddparity", 0, 0, 'o'}, {"onestopbit", 0, 0, '1'}, {"twostopbits", 0, 0, '2'}, + {"iflag", 1, 0, 'i'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"debug", 0, 0, 'd'}, @@ -166,7 +214,7 @@ int main(int argc, char **argv) if (argc == 0) usage(EXIT_SUCCESS); - while ((optc = getopt_long(argc, argv, "dhV78neo12s:", opttbl, NULL)) >= 0) { + while ((optc = getopt_long(argc, argv, "dhV78neo12s:i:", opttbl, NULL)) >= 0) { switch (optc) { case 'd': debug++; @@ -189,6 +237,9 @@ int main(int argc, char **argv) if (*end || speed <= 0) errx(EXIT_FAILURE, _("invalid speed: %s"), optarg); break; + case 'i': + parse_iflag(optarg, &set_iflag, &clr_iflag); + break; case 'V': printf(_("ldattach from %s\n"), PACKAGE_STRING); break; @@ -255,6 +306,10 @@ int main(int argc, char **argv) break; } ts.c_cflag |= CREAD; /* just to be on the safe side */ + + ts.c_iflag |= set_iflag; + ts.c_iflag &= ~clr_iflag; + if (tcsetattr(tty_fd, TCSAFLUSH, &ts) < 0) err(EXIT_FAILURE, _("cannot set terminal attributes for %s"), dev);