/* * KISS PTY bridge for max25-bcpr (HyBBX attach via kiss_link symlink). */ #define _GNU_SOURCE #include "bcpr/bcpr_kiss.h" #include #include #include #include #include #include #include #if defined(__linux__) #include #elif defined(__FreeBSD__) #include #else #include #endif static int ensure_dir(const char *path) { char tmp[256]; char *p; size_t len; if (!path || !path[0]) { return -1; } snprintf(tmp, sizeof(tmp), "%s", path); len = strlen(tmp); if (len == 0) { return -1; } if (tmp[len - 1] == '/') { tmp[len - 1] = '\0'; } for (p = tmp + 1; *p; p++) { if (*p == '/') { *p = '\0'; (void)mkdir(tmp, 0755); *p = '/'; } } return mkdir(tmp, 0755) == 0 || errno == EEXIST ? 0 : -1; } int bcpr_kiss_pty_open(bcpr_kiss_pty_t *kp, int idx, const char *link_path, const char *state_dir) { int master = -1, slave = -1; char slave_name[128]; char dir[128]; const char *slash; memset(kp, 0, sizeof(*kp)); kp->idx = idx; kp->master_fd = -1; kp->slave_fd = -1; snprintf(kp->link_path, sizeof(kp->link_path), "%s", link_path); slash = strrchr(link_path, '/'); if (slash && slash > link_path) { size_t n = (size_t)(slash - link_path); if (n >= sizeof(dir)) { n = sizeof(dir) - 1; } memcpy(dir, link_path, n); dir[n] = '\0'; (void)ensure_dir(dir); } else { (void)ensure_dir(state_dir); } if (openpty(&master, &slave, slave_name, NULL, NULL) != 0) { perror("max25-bcpr openpty"); return -1; } if (fchmod(slave, 0660) != 0) { perror("max25-bcpr fchmod kiss slave"); } else { struct group *gr = getgrnam("dialout"); if (gr == NULL) { gr = getgrnam("uucp"); } if (gr == NULL) { gr = getgrnam("tty"); } if (gr != NULL && fchown(slave, (uid_t)-1, gr->gr_gid) != 0) { perror("max25-bcpr fchown kiss slave"); } } unlink(link_path); if (symlink(slave_name, link_path) != 0) { perror("max25-bcpr symlink kiss_link"); close(slave); close(master); return -1; } fcntl(master, F_SETFL, O_NONBLOCK); kp->master_fd = master; close(slave); kp->slave_fd = -1; fprintf(stderr, "max25-bcpr: max25e0:bc%d KISS → %s -> %s\n", idx, link_path, slave_name); return 0; } void bcpr_kiss_pty_close(bcpr_kiss_pty_t *kp) { if (!kp) { return; } if (kp->slave_fd >= 0) { close(kp->slave_fd); kp->slave_fd = -1; } if (kp->master_fd >= 0) { close(kp->master_fd); kp->master_fd = -1; } if (kp->link_path[0]) { unlink(kp->link_path); } }