Refactor patty_kiss_tnc_new()

Refactor patty_kiss_tnc_new() into the following initialization methods:

    * init_sock()
    * init_device()
    * init_termios()
This commit is contained in:
XANTRONIX 2020-10-09 13:52:38 -04:00 committed by XANTRONIX Industrial
parent ab3679b788
commit 4f2f01ec0a

199
src/tnc.c
View file

@ -49,6 +49,112 @@ struct _patty_kiss_tnc {
offset_o;
};
static int init_sock(patty_kiss_tnc *tnc, patty_kiss_tnc_info *info) {
struct sockaddr_un addr;
if (strlen(info->device) > sizeof(addr.sun_path)) {
errno = EOVERFLOW;
goto error_overflow;
}
if ((tnc->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, info->device, sizeof(addr.sun_path)-1);
if (connect(tnc->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
return 0;
error_connect:
(void)close(tnc->fd);
error_socket:
error_overflow:
return -1;
}
static int init_termios(patty_kiss_tnc *tnc, patty_kiss_tnc_info *info) {
if (tcgetattr(tnc->fd, &tnc->attrs) < 0) {
goto error_tcgetattr;
}
memcpy(&tnc->attrs_old, &tnc->attrs, sizeof(tnc->attrs_old));
cfmakeraw(&tnc->attrs);
if (info->flags & PATTY_KISS_TNC_BAUD) {
cfsetspeed(&tnc->attrs, info->baud);
}
if (info->flags & PATTY_KISS_TNC_FLOW) {
switch (info->flow) {
case PATTY_KISS_TNC_FLOW_NONE:
break;
case PATTY_KISS_TNC_FLOW_CRTSCTS:
tnc->attrs.c_cflag |= CRTSCTS;
break;
case PATTY_KISS_TNC_FLOW_XONXOFF:
tnc->attrs.c_iflag |= IXON | IXOFF;
break;
}
}
if (tcflush(tnc->fd, TCIOFLUSH) < 0) {
goto error_tcflush;
}
if (tcsetattr(tnc->fd, TCSANOW, &tnc->attrs) < 0) {
goto error_tcsetattr;
}
return 0;
error_tcsetattr:
error_tcflush:
error_tcgetattr:
return -1;
}
static int init_device(patty_kiss_tnc *tnc, patty_kiss_tnc_info *info) {
struct stat st;
if (strcmp(info->device, "/dev/ptmx") == 0) {
int ptysub;
if (openpty(&tnc->fd, &ptysub, NULL, NULL, NULL) < 0) {
goto error;
}
} else if (stat(info->device, &st) < 0) {
goto error;
} else if ((st.st_mode & S_IFMT) == S_IFSOCK) {
if (init_sock(tnc, info) < 0) {
goto error;
}
} else {
if ((tnc->fd = open(info->device, O_RDWR | O_NOCTTY)) < 0) {
goto error;
}
}
tnc->opts |= TNC_CLOSE_ON_DESTROY;
return 0;
error:
return -1;
}
patty_kiss_tnc *patty_kiss_tnc_new(patty_kiss_tnc_info *info) {
patty_kiss_tnc *tnc;
@ -61,90 +167,21 @@ patty_kiss_tnc *patty_kiss_tnc_new(patty_kiss_tnc_info *info) {
}
if (info->flags & PATTY_KISS_TNC_DEVICE) {
struct stat st;
if (strcmp(info->device, "/dev/ptmx") == 0) {
int ptysub;
if (openpty(&tnc->fd, &ptysub, NULL, NULL, NULL) < 0) {
goto error_open;
}
} else if (stat(info->device, &st) < 0) {
goto error_stat;
} else if ((st.st_mode & S_IFMT) == S_IFSOCK) {
struct sockaddr_un addr;
if (strlen(info->device) > sizeof(addr.sun_path)) {
errno = EOVERFLOW;
goto error_overflow;
}
if ((tnc->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, info->device, sizeof(addr.sun_path)-1);
if (connect(tnc->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
} else {
if ((tnc->fd = open(info->device, O_RDWR | O_NOCTTY)) < 0) {
goto error_open;
}
if (init_device(tnc, info) < 0) {
goto error_init_device;
}
tnc->opts |= TNC_CLOSE_ON_DESTROY;
} else if (info->flags & PATTY_KISS_TNC_FD) {
tnc->fd = info->fd;
} else {
errno = EINVAL;
goto error_no_fd;
goto error_invalid;
}
if (isatty(tnc->fd) && ptsname(tnc->fd) == NULL) {
if (tcgetattr(tnc->fd, &tnc->attrs) < 0) {
goto error_tcgetattr;
if (isatty(tnc->fd)) {
if (init_termios(tnc, info) < 0) {
goto error_init_termios;
}
memcpy(&tnc->attrs_old, &tnc->attrs, sizeof(tnc->attrs_old));
cfmakeraw(&tnc->attrs);
if (info->flags & PATTY_KISS_TNC_BAUD) {
cfsetspeed(&tnc->attrs, info->baud);
}
if (info->flags & PATTY_KISS_TNC_FLOW) {
switch (info->flow) {
case PATTY_KISS_TNC_FLOW_NONE:
break;
case PATTY_KISS_TNC_FLOW_CRTSCTS:
tnc->attrs.c_cflag |= CRTSCTS;
break;
case PATTY_KISS_TNC_FLOW_XONXOFF:
tnc->attrs.c_iflag |= IXON | IXOFF;
break;
}
}
if (tcflush(tnc->fd, TCIOFLUSH) < 0) {
goto error_tcflush;
}
if (tcsetattr(tnc->fd, TCSANOW, &tnc->attrs) < 0) {
goto error_tcsetattr;
}
} else {
errno = 0;
}
memset(&tnc->stats, '\0', sizeof(tnc->stats));
@ -160,19 +197,13 @@ patty_kiss_tnc *patty_kiss_tnc_new(patty_kiss_tnc_info *info) {
return tnc;
error_tcflush:
error_tcsetattr:
error_tcgetattr:
error_connect:
error_init_termios:
if (info->flags & PATTY_KISS_TNC_DEVICE) {
(void)close(tnc->fd);
}
error_open:
error_no_fd:
error_socket:
error_overflow:
error_stat:
error_init_device:
error_invalid:
free(tnc->buf);
error_malloc_buf: