1 /* line discipline loading daemon
2 * open a serial device and attach a line discipline on it
5 * ldattach GIGASET_M101 /dev/ttyS0
7 * =====================================================================
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 * =====================================================================
19 #include <sys/types.h>
22 #include <sys/ioctl.h>
31 #define dbg(format, arg...) \
32 do { if (debug) fprintf(stderr , "%s:" format "\n" , progname , ## arg); } while (0)
34 #ifndef N_GIGASET_M101
35 # define N_GIGASET_M101 16
42 /* attach a line discipline ioctl */
44 # define TIOCSETD 0x5423
47 static const char *progname
;
55 /* currently supported line disciplines, plus some aliases */
56 static const struct ld_table ld_discs
[] =
69 { "SYNC_PPP", N_SYNC_PPP
},
70 { "SYNCPPP", N_SYNC_PPP
},
72 { "GIGASET_M101", N_GIGASET_M101
},
73 { "GIGASET", N_GIGASET_M101
},
74 { "M101", N_GIGASET_M101
},
79 static int lookup_table(const struct ld_table
*tab
, const char *str
)
81 const struct ld_table
*t
;
83 for (t
= tab
; t
&& t
->name
; t
++)
84 if (!strcasecmp(t
->name
, str
))
89 static void print_table(FILE *out
, const struct ld_table
*tab
)
91 const struct ld_table
*t
;
94 for (t
= tab
, i
= 1; t
&& t
->name
; t
++, i
++) {
95 fprintf(out
, " %-10s", t
->name
);
101 static void __attribute__((__noreturn__
)) usage(int exitcode
)
104 _("\nUsage: %s [ -dhV78neo12 ] [ -s <speed> ] <ldisc> <device>\n"),
106 fputs(_("\nKnown <ldisc> names:\n"), stderr
);
107 print_table(stderr
, ld_discs
);
112 static int my_cfsetspeed(struct termios
*ts
, int speed
)
115 * -- cfsetspeed() is able to translate number to Bxxx constants
117 if (cfsetspeed(ts
, speed
) == 0)
120 /* Nonstandard speeds
121 * -- we have to bypass glibc and set the speed manually (because
122 * glibc checks for speed and supports Bxxx bit rates only)...
124 #ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED
125 # define BOTHER 0010000 /* non standard rate */
126 dbg("using non-standard speeds");
127 ts
->c_ospeed
= ts
->c_ispeed
= speed
;
128 ts
->c_cflag
&= ~CBAUD
;
129 ts
->c_cflag
|= BOTHER
;
136 int main(int argc
, char **argv
)
140 int speed
= 0, bits
= '-', parity
= '-', stop
= '-';
145 static const struct option opttbl
[] = {
146 {"speed", 1, 0, 's'},
147 {"sevenbits", 0, 0, '7'},
148 {"eightbits", 0, 0, '8'},
149 {"noparity", 0, 0, 'n'},
150 {"evenparity", 0, 0, 'e'},
151 {"oddparity", 0, 0, 'o'},
152 {"onestopbit", 0, 0, '1'},
153 {"twostopbits", 0, 0, '2'},
155 {"version", 0, 0, 'V'},
156 {"debug", 0, 0, 'd'},
160 setlocale(LC_ALL
, "");
161 bindtextdomain(PACKAGE
, LOCALEDIR
);
165 progname
= program_invocation_short_name
;
169 while ((optc
= getopt_long(argc
, argv
, "dhV78neo12s:", opttbl
, NULL
)) >= 0) {
188 speed
= strtol(optarg
, &end
, 10);
189 if (*end
|| speed
<= 0)
190 errx(EXIT_FAILURE
, _("invalid speed: %s"), optarg
);
193 printf(_("ldattach from %s\n"), PACKAGE_STRING
);
198 warnx(_("invalid option"));
203 if (argc
- optind
!= 2)
206 /* parse line discipline specification */
207 ldisc
= lookup_table(ld_discs
, argv
[optind
]);
209 ldisc
= strtol(argv
[optind
], &end
, 0);
210 if (*end
|| ldisc
< 0)
211 errx(EXIT_FAILURE
, _("invalid line discipline: %s"), argv
[optind
]);
215 dev
= argv
[optind
+1];
216 if ((tty_fd
= open(dev
, O_RDWR
|O_NOCTTY
)) < 0)
217 err(EXIT_FAILURE
, _("cannot open %s"), dev
);
219 errx(EXIT_FAILURE
, _("%s is not a serial line"), dev
);
221 dbg("opened %s", dev
);
223 /* set line speed and format */
224 if (tcgetattr(tty_fd
, &ts
) < 0)
225 err(EXIT_FAILURE
, _("cannot get terminal attributes for %s"), dev
);
227 if (speed
&& my_cfsetspeed(&ts
, speed
) < 0)
228 errx(EXIT_FAILURE
, _("speed %d unsupported"), speed
);
231 ts
.c_cflag
&= ~CSTOPB
;
234 ts
.c_cflag
|= CSTOPB
;
239 ts
.c_cflag
= (ts
.c_cflag
& ~CSIZE
) | CS7
;
242 ts
.c_cflag
= (ts
.c_cflag
& ~CSIZE
) | CS8
;
247 ts
.c_cflag
&= ~(PARENB
|PARODD
);
250 ts
.c_cflag
|= PARENB
;
251 ts
.c_cflag
&= ~PARODD
;
254 ts
.c_cflag
|= (PARENB
|PARODD
);
257 ts
.c_cflag
|= CREAD
; /* just to be on the safe side */
258 if (tcsetattr(tty_fd
, TCSAFLUSH
, &ts
) < 0)
259 err(EXIT_FAILURE
, _("cannot set terminal attributes for %s"), dev
);
261 dbg("set to raw %d %c%c%c: cflag=0x%x",
262 speed
, bits
, parity
, stop
, ts
.c_cflag
);
264 /* Attach the line discpline. */
265 if (ioctl(tty_fd
, TIOCSETD
, &ldisc
) < 0)
266 err(EXIT_FAILURE
, _("cannot set line discipline"));
268 dbg("line discipline set to %d", ldisc
);
270 /* Go into background if not in debug mode. */
271 if (!debug
&& daemon(0, 0) < 0)
272 err(EXIT_FAILURE
, _("cannot daemonize"));
274 /* Sleep to keep the line discipline active. */