+
+int
+main(int argc, char *argv[])
+{
+ long tl;
+ char *t = NULL;
+ char *endptr = NULL;
+ unsigned int tui;
+ int oind, rxspdset, devset, c;
+ oind = rxspdset = devset = 0;
+
+ for (int i = 1; i < argc; i++) {
+ if (argv[i][0] == '-' && argv[i][1] >= '0' &&
+ argv[i][1] <= '9') {
+ if (asprintf(&t, "-s%s", argv[i] + 1) == -1) {
+ fprintf(stderr,
+ "%s: cannot convert -# to -s#\n",
+ argv[0]);
+
+ break;
+ } else {
+ argv[i] = t;
+ }
+ }
+ }
+
+ static struct option longopt[] = {
+ {"line", required_argument, NULL, 'l'},
+ {"speed", required_argument, NULL, 's'},
+ {"rx-speed", required_argument, NULL, 'i'},
+ {"echo", no_argument, NULL, 'h'},
+ {"canonical", no_argument, NULL, 'c'},
+ {"odd", no_argument, NULL, 'o'},
+ {"even", no_argument, NULL, 'e'},
+ {"hardware-rts-cts", no_argument, NULL, 'R'},
+ {"hardware-dtr-dsr", no_argument, NULL, 'r'},
+ {"software", no_argument, NULL, 'X'},
+ {"data", required_argument, NULL, 'D'},
+ {"delay", required_argument, NULL, 'd'},
+ {"min-chars", required_argument, NULL, 'm'},
+ {"stop-bits", no_argument, NULL, 'S'},
+ {"backspace", no_argument, NULL, 'b'},
+ {"translation", required_argument, NULL, 't'},
+ {"input-translation", required_argument, NULL, 'T'},
+ {"verbose", no_argument, NULL, 'v'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((c = getopt_long(argc, argv,
+ "D:T:d:i:l:m:s:t:RXbcehorv", longopt, &oind)) >= 0) {
+ switch (c) {
+ case 0:
+ break;
+ case 'b':
+ backspace ^= 1; break;
+ case 'c':
+ canonical ^= 1; break;
+ case 'R':
+ hard ^= 1; break;
+ case 'r':
+ hard ^= 2; break;
+ case 'X':
+ soft ^= 1; break;
+ case 'd':
+ tl = strtol(optarg, &endptr, 10);
+ if (errno != 0 || *endptr != '\0' || tl < 0) {
+ fprintf(stderr,
+ "%s: invalid character delay: %s\n",
+ argv[0], optarg);
+
+ goto ustusage;
+ } else {
+ chardelay = tl;
+ }
+ break;
+ case 'D':
+ if (optarg[1] != '\0' ||
+ !(optarg[0] >= '5' && optarg[0] <= '8')) {
+ fprintf(stderr,
+ "%s: invalid number of data bits: %s\n",
+ argv[0], optarg);
+
+ goto ustusage;
+ } else {
+ datab = optarg[0];
+ }
+ break;
+ case 'e':
+ parity ^= 1; break;
+ case 'o':
+ parity ^= 2; break;
+ case 'h':
+ half ^= 1; break;
+ case 'i': /* FALLTHROUGH */
+ case 's':
+ tui = strtoui(optarg, 1);
+ if (tui == uintmax) {
+ fprintf(stderr,
+ "%s: invalid speed: %s\n",
+ argv[0], optarg);
+
+ goto ustusage;
+ }
+ if (c == 'i') {
+ ispeed = tui; rxspdset = 1;
+ } else {
+ ospeed = tui;
+ ispeed = rxspdset ? ispeed : ospeed;
+ }
+ break;
+ case 'S':
+ stopb ^= 1; break;
+ case 'l':
+ if (devset) {
+ fprintf(stderr,
+ "%s: cannot specify multiple devices\n",
+ argv[0]);
+
+ goto ustusage;
+ }
+ if (strlen(optarg) > 58) {
+ fprintf(stderr, "%s: device name too long\n", argv[0]);
+ goto ustusage;
+ }
+ if (strchr(optarg, '/')) {
+ strcpy(line, optarg);
+ devset = 1;
+ } else {
+ sprintf(line, "/dev/%s", optarg);
+ devset = 1;
+ }
+ break;
+ case 'm':
+ tui = strtoui(optarg, 1);
+ if (tui == uintmax) {
+ fprintf(stderr,
+ "%s: invalid number of characters: %s\n",
+ argv[0], optarg);
+
+ goto ustusage;
+ }
+ minchars = tui;
+ break;
+ case 't':
+ if (chcktropts(&tropts, optarg)) {
+ fprintf(stderr,
+ "%s: invalid output translation option: %s\n",
+ argv[0], optarg);
+
+ goto ustusage;
+ }
+ break;
+ case 'T':
+ if (chcktropts(&itropts, optarg)) {
+ fprintf(stderr,
+ "%s: invalid input translation option: %s\n",
+ argv[0], optarg);
+
+ goto ustusage;
+ }
+ break;
+ case 'v':
+ verbose ^= 1; break;
+ default:
+ ustusage:
+ die(2, "usage: %s [--line | -l line] "
+ "[--speed | -s # | -#] [--rx-speed | -i #]\n"
+ " [--data-bits | -D #] "
+ "[--stop-bits | -S] [--even | -e] [--odd | -o]\n"
+ " [--hardware-rts-cts | -R] "
+ "[--hardware-dtr-dsr | -r] [--software | -X]\n"
+ " [--min-chars | -m #] [--echo | -h] "
+ "[--canonical | -c] [--delay | -d #]\n"
+ " [--translation | -t option] "
+ "[--input-translation | -T option]\n"
+ " [--verbose | -v] "
+ "[--backspace | -b]\n", argv[0]);
+ break;
+ }
+ }
+
+ if (t)
+ free(t);
+
+ if (isatty(STDIN_FILENO))
+ interactive = 1;
+
+ signal(SIGHUP, sighandl);
+ signal(SIGINT, sighandl);
+ signal(SIGQUIT, sighandl);
+ signal(SIGTERM, sighandl);
+
+ fd = openport();
+ if (interactive) pfd = openparent();
+
+ #ifdef __OpenBSD__
+ if (pledge("stdio rpath tty", NULL) < 0) {
+ perror("pledge");
+ die(1, "pledge failed, exiting now\n");
+ }
+ #endif
+
+ pthread_t readthread, writethread;
+ pthread_create(&writethread, NULL, writeport, NULL);
+ pthread_create(&readthread, NULL, readport, NULL);
+ pthread_join(writethread, NULL);
+ pthread_join(readthread, NULL);
+
+ /* unreachable */
+ return 0;
+}