#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, .flags = PATTY_KISS_TNC_BAUD | PATTY_KISS_TNC_FLOW, .baud = B9600, .flow = PATTY_KISS_TNC_FLOW_CRTSCTS }; 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 (strcmp(argv[1], "/dev/ptmx") == 0) { int ptysub; char ptyname[256]; if (openpty(&info.fd, &ptysub, ptyname, NULL, NULL) < 0) { fprintf(stderr, "%s: %s: %s\n", argv[0], "openpty()", strerror(errno)); goto error_open; } if (grantpt(info.fd) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], ptyname, "grantpt()", strerror(errno)); goto error_grantpt; } if (unlockpt(info.fd) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], ptyname, "unlockpt()", strerror(errno)); goto error_unlockpt; } fprintf(stderr, "pts %s\n", ptyname); } else { if ((info.fd = open(argv[1], O_RDWR | O_NOCTTY)) < 0) { fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "open()", argv[1], strerror(errno)); goto error_open; } } 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: error_grantpt: error_unlockpt: close(info.fd); error_open: return 1; }