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>
30 #define dbg(format, arg...) \
31 do { if (debug) fprintf(stderr , "%s:" format "\n" , progname , ## arg); } while (0)
33 #ifndef N_GIGASET_M101
34 # define N_GIGASET_M101 16
42 # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
45 /* attach a line discipline ioctl */
47 # define TIOCSETD 0x5423
50 static const char *progname;
53 /* currently supported line disciplines, plus some aliases */
54 static const struct ld_entry { const char *s; int v; }
67 { "SYNC_PPP", N_SYNC_PPP },
68 { "SYNCPPP", N_SYNC_PPP },
70 { "GIGASET_M101", N_GIGASET_M101 },
71 { "GIGASET", N_GIGASET_M101 },
72 { "M101", N_GIGASET_M101 },
76 /* look up line discipline code */
77 static int lookup_ld(const char *s)
81 for (i = 0; i < ARRAY_SIZE(ld_table); i++)
82 if (!strcasecmp(ld_table[i].s, s))
87 static void __attribute__((__noreturn__)) usage(int exitcode)
92 _("\nUsage: %s [ -dhV78neo12 ] [ -s <speed> ] <ldisc> <device>\n"),
94 fputs(_("\nKnown <ldisc> names:\n"), stderr);
95 for (i = 0; i < ARRAY_SIZE(ld_table); i++)
96 fprintf(stderr, " %s\n", ld_table[i].s);
100 static int my_cfsetspeed(struct termios *ts, int speed)
103 * -- cfsetspeed() is able to translate number to Bxxx constants
105 if (cfsetspeed(ts, speed) == 0)
108 /* Nonstandard speeds
109 * -- we have to bypass glibc and set the speed manually (because
110 * glibc checks for speed and supports Bxxx bit rates only)...
112 #ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED
113 # define BOTHER 0010000 /* non standard rate */
114 dbg("using non-standard speeds");
115 ts->c_ospeed = ts->c_ispeed = speed;
116 ts->c_cflag &= ~CBAUD;
117 ts->c_cflag |= BOTHER;
124 int main(int argc, char **argv)
128 int speed = 0, bits = '-', parity = '-', stop = '-';
133 static const struct option opttbl[] = {
134 {"speed", 1, 0, 's'},
135 {"sevenbits", 0, 0, '7'},
136 {"eightbits", 0, 0, '8'},
137 {"noparity", 0, 0, 'n'},
138 {"evenparity", 0, 0, 'e'},
139 {"oddparity", 0, 0, 'o'},
140 {"onestopbit", 0, 0, '1'},
141 {"twostopbits", 0, 0, '2'},
143 {"version", 0, 0, 'V'},
144 {"debug", 0, 0, 'd'},
149 setlocale(LC_ALL, "");
150 bindtextdomain(PACKAGE, LOCALEDIR);
154 progname = program_invocation_short_name;
158 while ((optc = getopt_long(argc, argv, "dhV78neo12s:", opttbl, NULL)) >= 0) {
177 speed = strtol(optarg, &end, 10);
178 if (*end || speed <= 0)
179 errx(EXIT_FAILURE, _("invalid speed: %s"), optarg);
182 printf(_("ldattach from %s\n"), PACKAGE_STRING);
187 warnx(_("invalid option"));
192 if (argc - optind != 2)
195 /* parse line discipline specification */
196 if ((ldisc = lookup_ld(argv[optind])) < 0) {
197 ldisc = strtol(argv[optind], &end, 0);
198 if (*end || ldisc < 0)
199 errx(EXIT_FAILURE, _("invalid line discipline: %s"), argv[optind]);
203 dev = argv[optind+1];
204 if ((tty_fd = open(dev, O_RDWR|O_NOCTTY)) < 0)
205 err(EXIT_FAILURE, _("cannot open %s"), dev);
207 errx(EXIT_FAILURE, _("%s is not a serial line"), dev);
209 dbg("opened %s", dev);
211 /* set line speed and format */
212 if (tcgetattr(tty_fd, &ts) < 0)
213 err(EXIT_FAILURE, _("cannot get terminal attributes for %s"), dev);
215 if (speed && my_cfsetspeed(&ts, speed) < 0)
216 errx(EXIT_FAILURE, _("speed %d unsupported"), speed);
219 ts.c_cflag &= ~CSTOPB;
222 ts.c_cflag |= CSTOPB;
227 ts.c_cflag = (ts.c_cflag & ~CSIZE) | CS7;
230 ts.c_cflag = (ts.c_cflag & ~CSIZE) | CS8;
235 ts.c_cflag &= ~(PARENB|PARODD);
238 ts.c_cflag |= PARENB;
239 ts.c_cflag &= ~PARODD;
242 ts.c_cflag |= (PARENB|PARODD);
245 ts.c_cflag |= CREAD; /* just to be on the safe side */
246 if (tcsetattr(tty_fd, TCSAFLUSH, &ts) < 0)
247 err(EXIT_FAILURE, _("cannot set terminal attributes for %s"), dev);
249 dbg("set to raw %d %c%c%c: cflag=0x%x",
250 speed, bits, parity, stop, ts.c_cflag);
252 /* Attach the line discpline. */
253 if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0)
254 err(EXIT_FAILURE, _("cannot set line discipline"));
256 dbg("line discipline set to %d", ldisc);
258 /* Go into background if not in debug mode. */
259 if (!debug && daemon(0, 0) < 0)
260 err(EXIT_FAILURE, _("cannot daemonize"));
262 /* Sleep to keep the line discipline active. */