]> git.sur5r.net Git - tio/blob - src/options.c
New upstream version 1.34
[tio] / src / options.c
1 /*
2  * tio - a simple TTY terminal I/O tool
3  *
4  * Copyright (c) 2014-2022  Martin Lund
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <stdbool.h>
29 #include <errno.h>
30 #include <getopt.h>
31 #include <termios.h>
32 #include <limits.h>
33 #include "options.h"
34 #include "error.h"
35
36 /* Default options */
37 struct option_t option =
38 {
39     .tty_device = "",
40     .baudrate = 115200,
41     .databits = 8,
42     .flow = "none",
43     .stopbits = 1,
44     .parity = "none",
45     .output_delay = 0,
46     .no_autoconnect = false,
47     .log = false,
48     .local_echo = false,
49     .timestamp = false,
50     .list_devices = false,
51     .log_filename = "",
52     .map = "",
53     .color = -1,
54 };
55
56 void print_help(char *argv[])
57 {
58     printf("Usage: %s [<options>] <tty-device>\n", argv[0]);
59     printf("\n");
60     printf("Options:\n");
61     printf("  -b, --baudrate <bps>        Baud rate (default: 115200)\n");
62     printf("  -d, --databits 5|6|7|8      Data bits (default: 8)\n");
63     printf("  -f, --flow hard|soft|none   Flow control (default: none)\n");
64     printf("  -s, --stopbits 1|2          Stop bits (default: 1)\n");
65     printf("  -p, --parity odd|even|none  Parity (default: none)\n");
66     printf("  -o, --output-delay <ms>     Output delay (default: 0)\n");
67     printf("  -n, --no-autoconnect        Disable automatic connect\n");
68     printf("  -e, --local-echo            Enable local echo\n");
69     printf("  -t, --timestamp             Enable line timestamp\n");
70     printf("  -L, --list-devices          List available serial devices\n");
71     printf("  -l, --log <filename>        Log to file\n");
72     printf("  -m, --map <flags>           Map special characters\n");
73     printf("  -c, --color <0..255>        Colorize tio text\n");
74     printf("  -v, --version               Display version\n");
75     printf("  -h, --help                  Display help\n");
76     printf("\n");
77     printf("See the man page for more details.\n");
78     printf("\n");
79     printf("In session, press ctrl-t q to quit.\n");
80     printf("\n");
81 }
82
83 long string_to_long(char *string)
84 {
85     long result;
86     char *end_token;
87
88     errno = 0;
89     result = strtol(string, &end_token, 10);
90     if ((errno != 0) || (*end_token != 0))
91     {
92         printf("Error: Invalid digit\n");
93         exit(EXIT_FAILURE);
94     }
95
96     return result;
97 }
98
99 void parse_options(int argc, char *argv[])
100 {
101     int c;
102
103     if (argc == 1)
104     {
105         print_help(argv);
106         exit(EXIT_SUCCESS);
107     }
108
109     while (1)
110     {
111         static struct option long_options[] =
112         {
113             {"baudrate",       required_argument, 0, 'b'},
114             {"databits",       required_argument, 0, 'd'},
115             {"flow",           required_argument, 0, 'f'},
116             {"stopbits",       required_argument, 0, 's'},
117             {"parity",         required_argument, 0, 'p'},
118             {"output-delay",   required_argument, 0, 'o'},
119             {"no-autoconnect", no_argument,       0, 'n'},
120             {"local-echo",     no_argument,       0, 'e'},
121             {"timestamp",      no_argument,       0, 't'},
122             {"list-devices",   no_argument,       0, 'L'},
123             {"log",            required_argument, 0, 'l'},
124             {"map",            required_argument, 0, 'm'},
125             {"color",          required_argument, 0, 'c'},
126             {"version",        no_argument,       0, 'v'},
127             {"help",           no_argument,       0, 'h'},
128             {0,                0,                 0,  0 }
129         };
130
131         /* getopt_long stores the option index here */
132         int option_index = 0;
133
134         /* Parse argument using getopt_long */
135         c = getopt_long(argc, argv, "b:d:f:s:p:o:netLl:m:c:vh", long_options, &option_index);
136
137         /* Detect the end of the options */
138         if (c == -1)
139             break;
140
141         switch (c)
142         {
143             case 0:
144                 /* If this option sets a flag, do nothing else now */
145                 if (long_options[option_index].flag != 0)
146                     break;
147                 printf("option %s", long_options[option_index].name);
148                 if (optarg)
149                     printf(" with arg %s", optarg);
150                 printf("\n");
151                 break;
152
153             case 'b':
154                 option.baudrate = string_to_long(optarg);
155                 break;
156
157             case 'd':
158                 option.databits = string_to_long(optarg);
159                 break;
160
161             case 'f':
162                 option.flow = optarg;
163                 break;
164
165             case 's':
166                 option.stopbits = string_to_long(optarg);
167                 break;
168
169             case 'p':
170                 option.parity = optarg;
171                 break;
172
173             case 'o':
174                 option.output_delay = string_to_long(optarg);
175                 break;
176
177             case 'n':
178                 option.no_autoconnect = true;
179                 break;
180
181             case 'e':
182                 option.local_echo = true;
183                 break;
184
185             case 't':
186                 option.timestamp = true;
187                 break;
188
189             case 'L':
190                 option.list_devices = true;
191                 break;
192
193             case 'l':
194                 option.log = true;
195                 option.log_filename = optarg;
196                 break;
197
198             case 'm':
199                 option.map = optarg;
200                 break;
201
202             case 'c':
203                 option.color = string_to_long(optarg);
204                 if (option.color > 255)
205                 {
206                     printf("Error: Invalid color code\n");
207                     exit(EXIT_FAILURE);
208                 }
209                 if (option.color < 0)
210                 {
211                     // Print available color codes
212                     printf("Available color codes:\n");
213                     for (int i=0; i<=255; i++)
214                     {
215                         printf(" \e[1;38;5;%dmThis is color code %d\e[0m\n", i, i);
216                     }
217                     exit(EXIT_SUCCESS);
218                 }
219                 break;
220
221             case 'v':
222                 printf("tio v%s\n", VERSION);
223                 printf("Copyright (c) 2014-2022 Martin Lund\n");
224                 printf("\n");
225                 printf("License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>.\n");
226                 printf("This is free software: you are free to change and redistribute it.\n");
227                 printf("There is NO WARRANTY, to the extent permitted by law.\n");
228                 exit(EXIT_SUCCESS);
229                 break;
230
231             case 'h':
232                 print_help(argv);
233                 exit(EXIT_SUCCESS);
234                 break;
235
236             case '?':
237                 /* getopt_long already printed an error message */
238                 exit(EXIT_FAILURE);
239                 break;
240
241             default:
242                 exit(EXIT_FAILURE);
243         }
244     }
245
246     if (option.list_devices)
247     {
248         return;
249     }
250
251     /* Assume first non-option is the tty device name */
252     if (optind < argc)
253         option.tty_device = argv[optind++];
254
255     if (strlen(option.tty_device) == 0)
256     {
257         printf("Error: Missing device name\n");
258         exit(EXIT_FAILURE);
259     }
260
261     /* Print any remaining command line arguments (unknown options) */
262     if (optind < argc)
263     {
264         printf("Error: unknown arguments: ");
265         while (optind < argc)
266             printf("%s ", argv[optind++]);
267         printf("\n");
268         exit(EXIT_FAILURE);
269     }
270 }