#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include static void usage(int argc, char **argv, const char *message, ...) { if (message != NULL) { va_list args; va_start(args, message); vfprintf(stderr, message, args); fprintf(stderr, "\n"); va_end(args); } fprintf(stderr, "usage: %s /dev/ttyXX|kiss.cap [path.sock] callsign\n", argv[0]); exit(1); } int main(int argc, char **argv) { patty_daemon *daemon; patty_ax25_if_kiss_tnc_info info = { .type = PATTY_AX25_IF_KISS_TNC_INFO_FD }; if (argc < 2) { usage(argc, argv, "No TNC device or KISS dump file provided"); } else if (argc < 3) { usage(argc, argv, "No socket path provided"); } else if (argc < 4) { usage(argc, argv, "No station callsign provided"); } else if (argc > 4) { usage(argc, argv, "Too many arguments provided"); } if ((info.fd = open(argv[1], O_RDWR)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "open()", argv[1], strerror(errno)); goto error_open; } if (isatty(info.fd) && grantpt(info.fd) == 0 && unlockpt(info.fd) == 0) { char *pts; if ((pts = ptsname(info.fd)) == NULL) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], argv[1], "ptsname()", strerror(errno)); goto error_open; } fprintf(stderr, "pts %s\n", pts); } else { struct termios t; memset(&t, '\0', sizeof(t)); t.c_cflag = CS8 | CREAD | HUPCL | CRTSCTS; t.c_iflag = IGNPAR; t.c_cc[VTIME] = 0; t.c_cc[VMIN] = 1; cfsetspeed(&t, B9600); if (tcsetattr(info.fd, TCSANOW, &t) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], argv[1], "tcsetattr()", strerror(errno)); } } errno = 0; if ((daemon = patty_daemon_new()) == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_daemon_new()", strerror(errno)); goto error_daemon_new; } if (argc >= 3) { if (patty_daemon_set_sock_path(daemon, argv[2]) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_daemon_set_sock_path()", strerror(errno)); goto error_daemon_set_sock_path; } } if (patty_daemon_init(daemon) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_daemon_init()", strerror(errno)); goto error_daemon_init; } if (patty_daemon_if_add(daemon, PATTY_AX25_IF_KISS_TNC, (patty_ax25_if_info *)&info, argv[3]) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_daemon_if_add()", strerror(errno)); goto error_daemon_if_add; } if (patty_daemon_route_add_default(daemon, "kiss0") < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "patty_daemon_route_add_default()", strerror(errno)); goto error_daemon_route_add_default; } if (patty_daemon_run(daemon) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], argv[1], "patty_daemon_run()", strerror(errno)); goto error_daemon_run; } patty_daemon_destroy(daemon); return 0; error_daemon_run: error_daemon_route_add_default: error_daemon_if_add: error_daemon_set_sock_path: error_daemon_init: patty_daemon_destroy(daemon); error_daemon_new: close(info.fd); error_open: return 1; }