Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
|
|
|
|
#include <patty/ax25.h>
|
|
|
|
|
|
|
|
patty_client *patty_client_new(const char *path) {
|
|
|
|
patty_client *client;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
|
|
|
|
if ((client = malloc(sizeof(*client))) == NULL) {
|
|
|
|
goto error_malloc_client;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((client->socks = patty_dict_new()) == NULL) {
|
|
|
|
goto error_dict_new;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((client->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
|
|
goto error_socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&addr, '\0', sizeof(addr));
|
|
|
|
addr.sun_family = AF_UNIX;
|
2020-08-07 17:59:16 -04:00
|
|
|
strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
|
|
|
|
if (connect(client->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
|
|
goto error_connect;
|
|
|
|
}
|
|
|
|
|
|
|
|
return client;
|
|
|
|
|
|
|
|
error_connect:
|
|
|
|
close(client->fd);
|
|
|
|
|
|
|
|
error_socket:
|
|
|
|
patty_dict_destroy(client->socks);
|
|
|
|
|
|
|
|
error_dict_new:
|
|
|
|
free(client);
|
|
|
|
|
|
|
|
error_malloc_client:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int request_close(patty_client *client,
|
|
|
|
int fd) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_CLOSE;
|
|
|
|
|
|
|
|
patty_client_close_request request = { fd };
|
|
|
|
patty_client_close_response response;
|
|
|
|
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((len = read(client->fd, &response, sizeof(response))) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
} else if (len != sizeof(response)) {
|
|
|
|
errno = EIO;
|
|
|
|
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return response.ret;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int destroy_sock(uint32_t key, void *value, void *ctx) {
|
|
|
|
patty_client *client = ctx;
|
|
|
|
patty_client_sock *sock = value;
|
|
|
|
|
|
|
|
(void)request_close(client, sock->fd);
|
|
|
|
|
|
|
|
free(sock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void patty_client_destroy(patty_client *client) {
|
|
|
|
close(client->fd);
|
|
|
|
|
|
|
|
(void)patty_dict_each(client->socks, destroy_sock, client);
|
|
|
|
patty_dict_destroy(client->socks);
|
|
|
|
|
|
|
|
free(client);
|
|
|
|
}
|
|
|
|
|
2020-08-24 16:12:33 -05:00
|
|
|
int patty_client_ping(patty_client *client) {
|
|
|
|
int call = PATTY_CLIENT_PING,
|
|
|
|
pong;
|
|
|
|
|
|
|
|
ssize_t len;
|
|
|
|
|
|
|
|
if ((len = write(client->fd, &call, sizeof(call))) < 0 || len == 0) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((len = read(client->fd, &pong, sizeof(pong))) < 0 || len == 0) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pong;
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (errno == 0 || errno == EIO) {
|
|
|
|
errno = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
int patty_client_socket(patty_client *client,
|
|
|
|
int proto,
|
|
|
|
int type) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_SOCKET;
|
|
|
|
|
|
|
|
patty_client_socket_request request = {
|
|
|
|
proto, type
|
|
|
|
};
|
|
|
|
|
|
|
|
patty_client_socket_response response;
|
|
|
|
patty_client_sock *sock;
|
|
|
|
|
|
|
|
int fd;
|
|
|
|
struct termios t;
|
|
|
|
|
|
|
|
if ((sock = malloc(sizeof(*sock))) == NULL) {
|
|
|
|
goto error_malloc_sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(client->fd, &response, sizeof(response)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
sock->fd = response.fd;
|
|
|
|
|
|
|
|
strncpy(sock->path, response.path, sizeof(sock->path));
|
|
|
|
|
|
|
|
if ((fd = open(sock->path, O_RDWR)) < 0) {
|
|
|
|
goto error_open;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tcgetattr(fd, &t) < 0) {
|
|
|
|
goto error_tcgetattr;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfmakeraw(&t);
|
|
|
|
|
|
|
|
if (tcsetattr(fd, TCSANOW, &t) < 0) {
|
|
|
|
goto error_tcsetattr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_dict_set(client->socks,
|
|
|
|
(uint32_t)fd,
|
|
|
|
sock) == NULL) {
|
|
|
|
goto error_dict_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
error_dict_set:
|
|
|
|
error_tcsetattr:
|
|
|
|
error_tcgetattr:
|
|
|
|
(void)close(fd);
|
|
|
|
|
|
|
|
error_open:
|
|
|
|
(void)request_close(client, sock->fd);
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
free(sock);
|
|
|
|
|
|
|
|
error_malloc_sock:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_client_setsockopt(patty_client *client,
|
|
|
|
int fd,
|
|
|
|
int opt,
|
|
|
|
void *data,
|
|
|
|
size_t len) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_SETSOCKOPT;
|
|
|
|
|
|
|
|
patty_client_setsockopt_request request = {
|
|
|
|
.opt = opt,
|
|
|
|
.len = len
|
|
|
|
};
|
|
|
|
|
|
|
|
patty_client_setsockopt_response response;
|
|
|
|
|
|
|
|
patty_client_sock *sock;
|
|
|
|
|
|
|
|
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
|
|
|
|
errno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get;
|
|
|
|
}
|
|
|
|
|
|
|
|
request.fd = sock->fd;
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, data, len) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(client->fd, &response, sizeof(response)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return response.ret;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
error_dict_get:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_client_bind(patty_client *client,
|
|
|
|
int fd,
|
|
|
|
patty_ax25_addr *addr) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_BIND;
|
|
|
|
|
|
|
|
patty_client_bind_request request;
|
|
|
|
patty_client_bind_response response;
|
|
|
|
|
|
|
|
patty_client_sock *sock;
|
|
|
|
|
|
|
|
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
|
|
|
|
errno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&request, '\0', sizeof(request));
|
|
|
|
|
|
|
|
request.fd = sock->fd;
|
|
|
|
|
|
|
|
memcpy(&request.addr, addr, sizeof(*addr));
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(client->fd, &response, sizeof(response)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return response.ret;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
error_dict_get:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_client_listen(patty_client *client,
|
|
|
|
int fd) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_LISTEN;
|
|
|
|
|
|
|
|
patty_client_listen_request request;
|
|
|
|
patty_client_listen_response response;
|
|
|
|
|
|
|
|
patty_client_sock *sock;
|
|
|
|
|
|
|
|
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
|
|
|
|
errno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get;
|
|
|
|
}
|
|
|
|
|
|
|
|
request.fd = sock->fd;
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(client->fd, &response, sizeof(response)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return response.ret;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
error_dict_get:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_client_accept(patty_client *client,
|
|
|
|
int fd,
|
|
|
|
patty_ax25_addr *peer) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_ACCEPT;
|
|
|
|
|
|
|
|
patty_client_accept_request request;
|
|
|
|
patty_client_accept_response response;
|
2020-08-12 00:19:46 -04:00
|
|
|
patty_client_accept_message message;
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
|
|
|
|
patty_client_sock *local,
|
|
|
|
*remote;
|
|
|
|
|
|
|
|
int pty;
|
|
|
|
struct termios t;
|
|
|
|
|
|
|
|
if ((local = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
|
|
|
|
errno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((remote = malloc(sizeof(*remote))) == NULL) {
|
|
|
|
goto error_malloc_remote;
|
|
|
|
}
|
|
|
|
|
|
|
|
request.fd = local->fd;
|
|
|
|
|
|
|
|
memset(&response, '\0', sizeof(response));
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
/*
|
|
|
|
* First, the server will tell us if the fd specified in accept() is indeed
|
|
|
|
* accepting connections.
|
|
|
|
*/
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
if (read(client->fd, &response, sizeof(response)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
if (response.ret < 0) {
|
|
|
|
errno = response.eno;
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
return response.ret;
|
|
|
|
}
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
/*
|
|
|
|
* Next, we will wait for the server to receive a SABM or SABME frame, and
|
|
|
|
* notify us via the listening socket that a connection has been accepted.
|
|
|
|
*/
|
|
|
|
if (read(fd, &message, sizeof(message)) < 0) {
|
|
|
|
goto error_io;
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
}
|
|
|
|
|
2020-08-12 00:19:46 -04:00
|
|
|
remote->fd = message.fd;
|
|
|
|
|
|
|
|
memcpy(peer, &message.peer, sizeof(*peer));
|
|
|
|
strncpy(remote->path, message.path, sizeof(remote->path));
|
|
|
|
|
Implement new patty client code
Implement new patty client code, replacing src/call.c with src/client.c
providing clients with an interface dealing with file descriptors valid
in their process space; this also obviates the need to open a Unix
domain socket to a patty server explicitly, and helps keep track of
sockets opened on the server, locally
Changes:
* Implement patty_client_new() to handle opening the server Unix
domain socket, and to allocate a dict for mapping server-side
sockets with current process file descriptors
* Reimplement all server calls in src/call.c around the new
patty_client type; calls which result in the creation of a
Unix98 PTY by the patty server now handle opening the local PTY
and setting the file descriptor to raw mode. Furthermore, these
calls deal exclusively in terms of current process file
descriptors
* Refactor src/server.c to use the new patty_client type and calls
* Refactor examples/client.c, examples/server.c, examples/ax25dump.c
to use the new patty_client type and calls
* Fix a bug in src/server.c, respond_accept() wherein a 0, rather
than the file descriptor of the socket, is sent to the client as a
return value
2020-08-01 20:21:01 -04:00
|
|
|
if ((pty = open(remote->path, O_RDWR)) < 0) {
|
|
|
|
goto error_open;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tcgetattr(pty, &t) < 0) {
|
|
|
|
goto error_tcgetattr;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfmakeraw(&t);
|
|
|
|
|
|
|
|
if (tcsetattr(pty, TCSANOW, &t) < 0) {
|
|
|
|
goto error_tcsetattr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patty_dict_set(client->socks,
|
|
|
|
(uint32_t)pty,
|
|
|
|
remote) == NULL) {
|
|
|
|
goto error_dict_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return pty;
|
|
|
|
|
|
|
|
error_tcsetattr:
|
|
|
|
error_tcgetattr:
|
|
|
|
error_dict_set:
|
|
|
|
(void)close(pty);
|
|
|
|
|
|
|
|
error_open:
|
|
|
|
(void)request_close(client, remote->fd);
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
free(remote);
|
|
|
|
|
|
|
|
error_malloc_remote:
|
|
|
|
error_dict_get:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_client_connect(patty_client *client,
|
|
|
|
int fd,
|
|
|
|
patty_ax25_addr *peer) {
|
|
|
|
enum patty_client_call call = PATTY_CLIENT_CONNECT;
|
|
|
|
|
|
|
|
patty_client_connect_request request;
|
|
|
|
patty_client_connect_response response;
|
|
|
|
|
|
|
|
patty_client_sock *sock;
|
|
|
|
|
|
|
|
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
|
|
|
|
errno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&request, '\0', sizeof(request));
|
|
|
|
|
|
|
|
request.fd = sock->fd;
|
|
|
|
|
|
|
|
memcpy(&request.peer, peer, sizeof(*peer));
|
|
|
|
|
|
|
|
if (write(client->fd, &call, sizeof(call)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(client->fd, &request, sizeof(request)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(client->fd, &response, sizeof(response)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = response.eno;
|
|
|
|
|
|
|
|
return response.ret;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
error_dict_get:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int patty_client_close(patty_client *client,
|
|
|
|
int fd) {
|
|
|
|
patty_client_sock *sock;
|
|
|
|
|
|
|
|
if ((sock = patty_dict_get(client->socks, (uint32_t)fd)) == NULL) {
|
|
|
|
errno = EBADF;
|
|
|
|
|
|
|
|
goto error_dict_get;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request_close(client, sock->fd) < 0) {
|
|
|
|
goto error_request_close;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (close(fd) < 0) {
|
|
|
|
goto error_close;
|
|
|
|
}
|
|
|
|
|
|
|
|
patty_dict_delete(client->socks, (uint32_t)fd);
|
|
|
|
|
|
|
|
free(sock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_close:
|
|
|
|
error_request_close:
|
|
|
|
error_dict_get:
|
|
|
|
return -1;
|
|
|
|
}
|