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 <tilman@imap.cc>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Tilman Schmidt 2010-03-01 10:45:47 +01:00 committed by Karel Zak
parent 7b549aff71
commit b091b880f9
2 changed files with 68 additions and 4 deletions

View File

@ -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)

View File

@ -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 <speed> ] <ldisc> <device>\n"),
_("\nUsage: %s [ -dhV78neo12 ] [ -s <speed> ] [ -i [-]<iflag> ] <ldisc> <device>\n"),
progname);
fputs(_("\nKnown <ldisc> names:\n"), stderr);
print_table(stderr, ld_discs);
fputs(_("\nKnown <iflag> 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);