]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - sys-utils/ldattach.c
docs: update year in libs docs
[thirdparty/util-linux.git] / sys-utils / ldattach.c
index 2917d4e833b1e4fbc4645afabd98f827c6604a9d..c2d2f8397a86003d1fd90b29ec117563581518d2 100644 (file)
 #include <unistd.h>
 
 #include "c.h"
+#include "all-io.h"
 #include "nls.h"
 #include "strutils.h"
 #include "closestream.h"
 
+#include <signal.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include <linux/tty.h>         /* for N_GSM0710 */
+
+#ifdef LINUX_GSMMUX_H
+# include <linux/gsmmux.h>     /* Add by guowenxue */
+#else
+struct gsm_config
+{
+       unsigned int adaption;
+       unsigned int encapsulation;
+       unsigned int initiator;
+       unsigned int t1;
+       unsigned int t2;
+       unsigned int t3;
+       unsigned int n2;
+       unsigned int mru;
+       unsigned int mtu;
+       unsigned int k;
+       unsigned int i;
+       unsigned int unused[8];         /* Padding for expansion without
+                                          breaking stuff */
+};
+# define GSMIOC_GETCONF                _IOR('G', 0, struct gsm_config)
+# define GSMIOC_SETCONF                _IOW('G', 1, struct gsm_config)
+#endif
+
 #ifndef N_GIGASET_M101
 # define N_GIGASET_M101 16
 #endif
 # define N_PPS 18
 #endif
 
+#ifndef N_GSM0710
+# define N_GSM0710 21
+#endif
+
+#define MAXINTROPARMLEN 32
+
 /* attach a line discipline ioctl */
 #ifndef TIOCSETD
 # define TIOCSETD   0x5423
 #endif
 
-static const char *progname;
 static int debug = 0;
 
 struct ld_table {
@@ -66,11 +101,12 @@ static const struct ld_table ld_discs[] = {
        { "SYNC_PPP",           N_SYNC_PPP },
        { "SYNCPPP",            N_SYNC_PPP },
        { "HCI",                N_HCI },
-       { "PPS",                N_PPS },
+       { "GIGASET_M101",       N_GIGASET_M101 },
        { "M101",               N_GIGASET_M101 },
        { "GIGASET",            N_GIGASET_M101 },
-       { "GIGASET_M101",       N_GIGASET_M101 },
-       { NULL,                 0 }
+       { "PPS",                N_PPS },
+       { "GSM0710",            N_GSM0710},
+       { NULL, 0 }
 };
 
 /* known c_iflag names */
@@ -94,18 +130,22 @@ static const struct ld_table ld_iflags[] =
        { NULL,         0 }
 };
 
-void dbg(char *fmt, ...)
+static void dbg(char *fmt, ...)
 {
        va_list args;
 
        if (debug == 0)
                return;
        fflush(NULL);
-       fprintf(stderr, "%s: ", program_invocation_short_name);
        va_start(args, fmt);
+#ifdef HAVE_VWARNX
+       vwarnx(fmt, args);
+#else
+       fprintf(stderr, "%s: ", program_invocation_short_name);
        vfprintf(stderr, fmt, args);
-       va_end(args);
        fprintf(stderr, "\n");
+#endif
+       va_end(args);
        fflush(NULL);
        return;
 }
@@ -126,8 +166,8 @@ static void print_table(FILE * out, const struct ld_table *tab)
        int i;
 
        for (t = tab, i = 1; t && t->name; t++, i++) {
-               fprintf(out, "  %-10s", t->name);
-               if (!(i % 6))
+               fprintf(out, "  %-12s", t->name);
+               if (!(i % 5))
                        fputc('\n', out);
        }
 }
@@ -141,7 +181,7 @@ static int parse_iflag(char *str, int *set_iflag, int *clr_iflag)
                if (*s == '-')
                        s++;
                if ((iflag = lookup_table(ld_iflags, s)) < 0)
-                       iflag = strtol_or_err(s, _("invalid iflag"));
+                       iflag = strtos32_or_err(s, _("invalid iflag"));
                if (s > str && *(s - 1) == '-')
                        *clr_iflag |= iflag;
                else
@@ -152,16 +192,21 @@ static int parse_iflag(char *str, int *set_iflag, int *clr_iflag)
 }
 
 
-static void __attribute__ ((__noreturn__)) usage(int exitcode)
+static void __attribute__((__noreturn__)) usage(void)
 {
-       FILE *out = exitcode == EXIT_SUCCESS ? stdout : stderr;
+       FILE *out = stdout;
 
        fputs(USAGE_HEADER, out);
        fprintf(out, _(" %s [options] <ldisc> <device>\n"), program_invocation_short_name);
-       fputs(USAGE_OPTIONS, out);
 
+       fputs(USAGE_SEPARATOR, out);
+       fputs(_("Attach a line discipline to a serial line.\n"), out);
+
+       fputs(USAGE_OPTIONS, out);
        fputs(_(" -d, --debug             print verbose messages to stderr\n"), out);
        fputs(_(" -s, --speed <value>     set serial line speed\n"), out);
+       fputs(_(" -c, --intro-command <string> intro sent before ldattach\n"), out);
+       fputs(_(" -p, --pause <seconds>   pause between intro and ldattach\n"), out);
        fputs(_(" -7, --sevenbits         set character size to 7 bits\n"), out);
        fputs(_(" -8, --eightbits         set character size to 8 bits\n"), out);
        fputs(_(" -n, --noparity          set parity to none\n"), out);
@@ -172,15 +217,17 @@ static void __attribute__ ((__noreturn__)) usage(int exitcode)
        fputs(_(" -i, --iflag [-]<iflag>  set input mode flag\n"), out);
 
        fputs(USAGE_SEPARATOR, out);
-       fputs(USAGE_HELP, out);
-       fputs(USAGE_VERSION, out);
+       printf(USAGE_HELP_OPTIONS(25));
+
        fputs(_("\nKnown <ldisc> names:\n"), out);
        print_table(out, ld_discs);
+       fputs(USAGE_SEPARATOR, out);
+
        fputs(_("\nKnown <iflag> names:\n"), out);
        print_table(out, ld_iflags);
-       fputc('\n', out);
-       fprintf(out, USAGE_MAN_TAIL("ldattach(8)"));
-       exit(exitcode);
+
+       printf(USAGE_MAN_TAIL("ldattach(8)"));
+       exit(EXIT_SUCCESS);
 }
 
 static int my_cfsetspeed(struct termios *ts, int speed)
@@ -195,7 +242,7 @@ static int my_cfsetspeed(struct termios *ts, int speed)
         * -- we have to bypass glibc and set the speed manually (because glibc
         *    checks for speed and supports Bxxx bit rates only)...
         */
-#ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED
+#if _HAVE_STRUCT_TERMIOS_C_ISPEED
 # define BOTHER 0010000                /* non standard rate */
        dbg("using non-standard speeds");
        ts->c_ospeed = ts->c_ispeed = speed;
@@ -207,6 +254,30 @@ static int my_cfsetspeed(struct termios *ts, int speed)
 #endif
 }
 
+static void handler(int s)
+{
+       dbg("got SIG %i -> exiting", s);
+       exit(EXIT_SUCCESS);
+}
+
+static void gsm0710_set_conf(int tty_fd)
+{
+       struct gsm_config c;
+
+       /* Add by guowenxue */
+       /*  get n_gsm configuration */
+       ioctl(tty_fd, GSMIOC_GETCONF, &c);
+       /*  we are initiator and need encoding 0 (basic) */
+       c.initiator = 1;
+       c.encapsulation = 0;
+       /*  our modem defaults to a maximum size of 127 bytes */
+       c.mru = 127;
+       c.mtu = 127;
+       /*  set the new configuration */
+       ioctl(tty_fd, GSMIOC_SETCONF, &c);
+       /* Add by guowenxue end*/
+}
+
 int main(int argc, char **argv)
 {
        int tty_fd;
@@ -216,6 +287,9 @@ int main(int argc, char **argv)
        int ldisc;
        int optc;
        char *dev;
+       int intropause = 1;
+       char *introparm = NULL;
+
        static const struct option opttbl[] = {
                {"speed", required_argument, NULL, 's'},
                {"sevenbits", no_argument, NULL, '7'},
@@ -229,21 +303,25 @@ int main(int argc, char **argv)
                {"help", no_argument, NULL, 'h'},
                {"version", no_argument, NULL, 'V'},
                {"debug", no_argument, NULL, 'd'},
+               {"intro-command", no_argument, NULL, 'c'},
+               {"pause", no_argument, NULL, 'p'},
                {NULL, 0, NULL, 0}
        };
 
+       signal(SIGKILL, handler);
+       signal(SIGINT, handler);
+
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
-       atexit(close_stdout);
+       close_stdout_atexit();
 
        /* parse options */
-       progname = program_invocation_short_name;
-
        if (argc == 0)
-               usage(EXIT_SUCCESS);
+               errx(EXIT_FAILURE, _("bad usage"));
+
        while ((optc =
-               getopt_long(argc, argv, "dhV78neo12s:i:", opttbl,
+               getopt_long(argc, argv, "dhV78neo12s:i:c:p:", opttbl,
                            NULL)) >= 0) {
                switch (optc) {
                case 'd':
@@ -263,29 +341,50 @@ int main(int argc, char **argv)
                        parity = optc;
                        break;
                case 's':
-                       speed = strtol_or_err(optarg, _("invalid speed"));
+                       speed = strtos32_or_err(optarg, _("invalid speed argument"));
+                       break;
+               case 'p':
+                       intropause = strtou32_or_err(optarg, _("invalid pause argument"));
+                       if (intropause > 10)
+                               errx(EXIT_FAILURE, "invalid pause: %s", optarg);
+                       break;
+               case 'c':
+                       introparm = optarg;
                        break;
                case 'i':
                        parse_iflag(optarg, &set_iflag, &clr_iflag);
                        break;
+
                case 'V':
-                       printf(UTIL_LINUX_VERSION);
-                       return EXIT_SUCCESS;
+                       print_version(EXIT_SUCCESS);
                case 'h':
-                       usage(EXIT_SUCCESS);
+                       usage();
                default:
-                       warnx(_("invalid option"));
-                       usage(EXIT_FAILURE);
+                       errtryhelp(EXIT_FAILURE);
                }
        }
 
-       if (argc - optind != 2)
-               usage(EXIT_FAILURE);
-
+       if (argc - optind != 2) {
+               warnx(_("not enough arguments"));
+               errtryhelp(EXIT_FAILURE);
+       }
        /* parse line discipline specification */
        ldisc = lookup_table(ld_discs, argv[optind]);
        if (ldisc < 0)
-               ldisc = strtol_or_err(argv[optind], _("invalid line discipline"));
+               ldisc = strtos32_or_err(argv[optind], _("invalid line discipline argument"));
+
+       /* ldisc specific option settings */
+       if (ldisc == N_GIGASET_M101) {
+               /* device specific defaults for line speed and data format */
+               if (speed == 0)
+                       speed = 115200;
+               if (bits == '-')
+                       bits = '8';
+               if (parity == '-')
+                       parity = 'n';
+               if (stop == '-')
+                       stop = '1';
+       }
 
        /* open device */
        dev = argv[optind + 1];
@@ -356,12 +455,29 @@ int main(int argc, char **argv)
        dbg("set to raw %d %c%c%c: cflag=0x%x",
            speed, bits, parity, stop, ts.c_cflag);
 
-       /* Attach the line discpline. */
+       if (introparm && *introparm)
+       {
+               dbg("intro command is '%s'", introparm);
+               if (write_all(tty_fd, introparm, strlen(introparm)) != 0)
+                       err(EXIT_FAILURE,
+                           _("cannot write intro command to %s"), dev);
+
+               if (intropause) {
+                       dbg("waiting for %d seconds", intropause);
+                       sleep(intropause);
+               }
+       }
+
+       /* Attach the line discipline. */
        if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0)
                err(EXIT_FAILURE, _("cannot set line discipline"));
 
        dbg("line discipline set to %d", ldisc);
 
+       /* ldisc specific post-attach actions */
+       if (ldisc == N_GSM0710)
+               gsm0710_set_conf(tty_fd);
+
        /* Go into background if not in debug mode. */
        if (!debug && daemon(0, 0) < 0)
                err(EXIT_FAILURE, _("cannot daemonize"));