Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c80995256 | |||
| 299cfcabb5 | |||
| b47cb98a69 | |||
| cb6509861f | |||
| 2f0cea6f73 | |||
| 015da8a55e |
+129
-42
@@ -55,14 +55,17 @@ static struct ttynvt_param {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
pthread_mutex_t tty_lock;
|
pthread_mutex_t tty_lock;
|
||||||
pthread_mutex_t poll_lock;
|
pthread_mutex_t poll_lock;
|
||||||
|
pthread_mutex_t read_lock;
|
||||||
|
pthread_mutex_t write_lock;
|
||||||
|
pthread_mutex_t ioctl_lock;
|
||||||
pthread_t ptid_poll;
|
pthread_t ptid_poll;
|
||||||
pthread_t ptid_read;
|
pthread_t ptid_read;
|
||||||
|
|
||||||
struct fuse_pollhandle *ph;
|
struct fuse_pollhandle *ph;
|
||||||
|
|
||||||
volatile int rel_pending;
|
volatile int rel_pending;
|
||||||
volatile int slave_suspended; /*waiting for application to read data */
|
volatile int slave_suspended; /* Waiting for application to read data */
|
||||||
volatile int master_suspended; /*server is not ready to receive data */
|
volatile int master_suspended; /* Server is not ready to receive data */
|
||||||
struct pollfd fds[3];
|
struct pollfd fds[3];
|
||||||
|
|
||||||
char net_buf[NET_BUF_SIZE];
|
char net_buf[NET_BUF_SIZE];
|
||||||
@@ -80,8 +83,18 @@ typedef struct {
|
|||||||
int epipe;
|
int epipe;
|
||||||
|
|
||||||
tn_ctx_t *tn;
|
tn_ctx_t *tn;
|
||||||
|
|
||||||
|
int seq;
|
||||||
|
struct ttynvt_cli_s *cli;
|
||||||
} ttynvt_t;
|
} ttynvt_t;
|
||||||
|
|
||||||
|
static ttynvt_t *ptty = NULL;
|
||||||
|
|
||||||
|
typedef struct ttynvt_cli_s {
|
||||||
|
int id;
|
||||||
|
ttynvt_t *tty;
|
||||||
|
struct ttynvt_cli_s *next;
|
||||||
|
} ttynvt_cli_t;
|
||||||
|
|
||||||
static pthread_mutex_t access_lock = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t access_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
@@ -114,7 +127,6 @@ static void ttynvt_interrupted(fuse_req_t req, void *data)
|
|||||||
pthread_kill(thread, SIGUSR2);
|
pthread_kill(thread, SIGUSR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _ttynvt_sleep_us(unsigned int tus)
|
static void _ttynvt_sleep_us(unsigned int tus)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
@@ -143,7 +155,6 @@ static int _check_dev(void)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _fd_close(int fd)
|
static void _fd_close(int fd)
|
||||||
{
|
{
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
@@ -406,24 +417,49 @@ static void _ttynvt_ctx_destroy(ttynvt_t * tty)
|
|||||||
|
|
||||||
static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty;
|
ttynvt_t *tty = ptty;
|
||||||
|
ttynvt_cli_t *tty_cli;
|
||||||
char *slave_name;
|
char *slave_name;
|
||||||
struct termios ios;
|
struct termios ios;
|
||||||
int fd;
|
int fd;
|
||||||
int res;
|
int res;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
pthread_mutex_lock(&access_lock);
|
|
||||||
|
|
||||||
nvt_log(LOG_INFO, "Connecting to server: %s\n", ttynvt_param.server);
|
tty_cli = calloc(1, sizeof(ttynvt_cli_t));
|
||||||
|
if (!tty_cli)
|
||||||
tty = _ttynvt_ctx_create();
|
|
||||||
if (!tty)
|
|
||||||
{
|
{
|
||||||
fuse_reply_err(req, ENOMEM);
|
fuse_reply_err(req, ENOMEM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&access_lock);
|
||||||
|
|
||||||
|
if (tty == NULL)
|
||||||
|
tty = _ttynvt_ctx_create();
|
||||||
|
if (!tty)
|
||||||
|
{
|
||||||
|
fuse_reply_err(req, ENOMEM);
|
||||||
|
free(tty_cli);
|
||||||
|
pthread_mutex_unlock(&access_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty_cli->id = tty->seq++;
|
||||||
|
tty_cli->tty = tty;
|
||||||
|
tty_cli->next = tty->cli;
|
||||||
|
|
||||||
|
tty->cli = tty_cli;
|
||||||
|
|
||||||
|
nvt_log(LOG_INFO, "Client open (%d)\n", tty_cli->id);
|
||||||
|
|
||||||
|
if (ptty)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ptty = tty;
|
||||||
|
|
||||||
|
nvt_log(LOG_INFO, "Connecting to server: %s\n", ttynvt_param.server);
|
||||||
|
|
||||||
fd = socket_create_client(ttynvt_param.server);
|
fd = socket_create_client(ttynvt_param.server);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
@@ -435,7 +471,7 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
tty->fds[FD_NET].events = POLLIN;
|
tty->fds[FD_NET].events = POLLIN;
|
||||||
tty->net_cnt = 0;
|
tty->net_cnt = 0;
|
||||||
|
|
||||||
if ((fd = open("/dev/ptmx", O_RDWR)) < 0) /* open master */
|
if ((fd = open("/dev/ptmx", O_RDWR)) < 0) /* Open master */
|
||||||
goto open_err;
|
goto open_err;
|
||||||
|
|
||||||
tty->fds[FD_MASTER].fd = fd;
|
tty->fds[FD_MASTER].fd = fd;
|
||||||
@@ -453,11 +489,11 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
if (ioctl(fd, TCSETS, &ios) < 0)
|
if (ioctl(fd, TCSETS, &ios) < 0)
|
||||||
goto open_err;
|
goto open_err;
|
||||||
|
|
||||||
grantpt(fd); /* change permission of slave */
|
grantpt(fd); /* Change permission of slave */
|
||||||
unlockpt(fd); /* unlock slave */
|
unlockpt(fd); /* Unlock slave */
|
||||||
slave_name = ptsname(fd); /* get name of slave */
|
slave_name = ptsname(fd); /* Get name of slave */
|
||||||
|
|
||||||
if ((fd = open(slave_name, O_RDWR | O_NOCTTY)) < 0) /* open slave */
|
if ((fd = open(slave_name, O_RDWR | O_NOCTTY)) < 0) /* Open slave */
|
||||||
goto open_err;
|
goto open_err;
|
||||||
|
|
||||||
ioctl(fd, TCGETS, &tty->tio);
|
ioctl(fd, TCGETS, &tty->tio);
|
||||||
@@ -478,26 +514,34 @@ static void ttynvt_open(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
|
|
||||||
if ((res = pthread_mutex_init(&tty->tty_lock, NULL) < 0) ||
|
if ((res = pthread_mutex_init(&tty->tty_lock, NULL) < 0) ||
|
||||||
(res = pthread_mutex_init(&tty->poll_lock, NULL) < 0) ||
|
(res = pthread_mutex_init(&tty->poll_lock, NULL) < 0) ||
|
||||||
|
(res = pthread_mutex_init(&tty->ioctl_lock, NULL) < 0) ||
|
||||||
|
(res = pthread_mutex_init(&tty->read_lock, NULL) < 0) ||
|
||||||
|
(res = pthread_mutex_init(&tty->write_lock, NULL) < 0) ||
|
||||||
(res = pthread_create(&tty->ptid_poll, NULL, &_read_net, tty)))
|
(res = pthread_create(&tty->ptid_poll, NULL, &_read_net, tty)))
|
||||||
{
|
{
|
||||||
errno = res;
|
errno = res;
|
||||||
goto open_err;
|
goto open_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->fh = (uintptr_t) tty;
|
nvt_log(LOG_INFO, "Connected to server: %s\n", ttynvt_param.server);
|
||||||
|
|
||||||
|
out:
|
||||||
|
info->fh = (uintptr_t) tty_cli;
|
||||||
info->nonseekable = 1;
|
info->nonseekable = 1;
|
||||||
info->direct_io = 1;
|
info->direct_io = 1;
|
||||||
|
|
||||||
nvt_log(LOG_INFO, "Connected to server: %s\n", ttynvt_param.server);
|
|
||||||
|
|
||||||
fuse_reply_open(req, info);
|
fuse_reply_open(req, info);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&access_lock);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
open_err:
|
open_err:
|
||||||
for (n = 0; n < 3; n++)
|
for (n = 0; n < 3; n++)
|
||||||
_fd_close(tty->fds[n].fd);
|
_fd_close(tty->fds[n].fd);
|
||||||
|
|
||||||
|
free(tty_cli);
|
||||||
_ttynvt_ctx_destroy(tty);
|
_ttynvt_ctx_destroy(tty);
|
||||||
|
ptty = NULL;
|
||||||
|
|
||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
|
|
||||||
@@ -511,11 +555,14 @@ static void
|
|||||||
ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
||||||
struct fuse_file_info *info)
|
struct fuse_file_info *info)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_cli_t *tty_cli = (ttynvt_cli_t *) (uintptr_t) info->fh;
|
||||||
|
ttynvt_t *tty = tty_cli->tty;
|
||||||
char buf[TMP_BUF_SIZE];
|
char buf[TMP_BUF_SIZE];
|
||||||
int res, nr;
|
int res, nr;
|
||||||
|
|
||||||
DBG2("%s\n", __func__);
|
pthread_mutex_lock(&tty->read_lock);
|
||||||
|
|
||||||
|
DBG2("%s (%d)\n", __func__, tty_cli->id);
|
||||||
|
|
||||||
if (tty->error)
|
if (tty->error)
|
||||||
{
|
{
|
||||||
@@ -529,7 +576,7 @@ ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
|||||||
else
|
else
|
||||||
fuse_reply_err(req, EBADFD);
|
fuse_reply_err(req, EBADFD);
|
||||||
|
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > TMP_BUF_SIZE)
|
if (size > TMP_BUF_SIZE)
|
||||||
@@ -556,36 +603,42 @@ ttynvt_read(fuse_req_t req, size_t size, off_t off,
|
|||||||
{
|
{
|
||||||
DBG2("%s: error: %m\n", __func__);
|
DBG2("%s: error: %m\n", __func__);
|
||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG2("%s: fd=%d: sz=%u/%u: '%.*s'\n", __func__,
|
DBG2("%s (%d): fd=%d: sz=%u/%u: '%.*s'\n", __func__,
|
||||||
tty->fds[FD_SLAVE].fd, res, (int)size, res, buf);
|
tty_cli->id, tty->fds[FD_SLAVE].fd, res, (int)size, res, buf);
|
||||||
|
|
||||||
fuse_reply_buf(req, buf, res);
|
fuse_reply_buf(req, buf, res);
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&tty->read_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
||||||
struct fuse_file_info *info)
|
struct fuse_file_info *info)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_cli_t *tty_cli = (ttynvt_cli_t *) (uintptr_t) info->fh;
|
||||||
|
ttynvt_t *tty = tty_cli->tty;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
DBG2("%s: fd=%d: sz=%u: '%.*s'\n", __func__,
|
pthread_mutex_lock(&tty->write_lock);
|
||||||
tty->fds[FD_SLAVE].fd, (int)size, (int)size, data);
|
|
||||||
|
DBG2("%s (%d): fd=%d: sz=%u: '%.*s'\n", __func__,
|
||||||
|
tty_cli->id, tty->fds[FD_SLAVE].fd, (int)size, (int)size, data);
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
fuse_reply_write(req, 0);
|
fuse_reply_write(req, 0);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tty->error)
|
if (tty->error)
|
||||||
{
|
{
|
||||||
DBG2("%s: tty->error=%d\n", __func__, tty->error);
|
DBG2("%s: tty->error=%d\n", __func__, tty->error);
|
||||||
fuse_reply_err(req, EPIPE);
|
fuse_reply_err(req, EPIPE);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = write(tty->fds[FD_SLAVE].fd, data, size);
|
res = write(tty->fds[FD_SLAVE].fd, data, size);
|
||||||
@@ -594,7 +647,7 @@ ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
|||||||
DBG2("%s: error: %m\n", __func__);
|
DBG2("%s: error: %m\n", __func__);
|
||||||
tty->error = 1;
|
tty->error = 1;
|
||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
else if (res != (int)size)
|
else if (res != (int)size)
|
||||||
{
|
{
|
||||||
@@ -603,6 +656,9 @@ ttynvt_write(fuse_req_t req, const char *data, size_t size, off_t off,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fuse_reply_write(req, res);
|
fuse_reply_write(req, res);
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&tty->write_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int baudrate(speed_t speed)
|
static int baudrate(speed_t speed)
|
||||||
@@ -780,7 +836,8 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
struct fuse_file_info *info, unsigned int flags,
|
struct fuse_file_info *info, unsigned int flags,
|
||||||
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_cli_t *tty_cli = (ttynvt_cli_t *) (uintptr_t) info->fh;
|
||||||
|
ttynvt_t *tty = tty_cli->tty;
|
||||||
struct termios2 *tio = &tty->tio;
|
struct termios2 *tio = &tty->tio;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
unsigned int tiocm, baud;
|
unsigned int tiocm, baud;
|
||||||
@@ -790,14 +847,16 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
uint32_t byte4;
|
uint32_t byte4;
|
||||||
|
|
||||||
DBG("%s: cmd=%s arg=%p ibuf=%p:%u obuf=:%u\n", __func__,
|
pthread_mutex_lock(&tty->ioctl_lock);
|
||||||
_ioctl_name(cmd), arg, in_buf,
|
|
||||||
|
DBG("%s (%d): cmd=%s arg=%p ibuf=%p:%u obuf=:%u\n", __func__,
|
||||||
|
tty_cli->id, _ioctl_name(cmd), arg, in_buf,
|
||||||
(unsigned int)in_bufsz, (unsigned int)out_bufsz);
|
(unsigned int)in_bufsz, (unsigned int)out_bufsz);
|
||||||
|
|
||||||
if (ttynvt_param.raw)
|
if (ttynvt_param.raw)
|
||||||
{
|
{
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
@@ -988,7 +1047,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize));
|
fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize));
|
||||||
break;
|
break;
|
||||||
@@ -999,7 +1058,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
fuse_reply_err(req, errno);
|
fuse_reply_err(req, errno);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize));
|
fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize));
|
||||||
break;
|
break;
|
||||||
@@ -1060,17 +1119,21 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_mutex_unlock(&tty->ioctl_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ttynvt_poll(fuse_req_t req, struct fuse_file_info *info,
|
ttynvt_poll(fuse_req_t req, struct fuse_file_info *info,
|
||||||
struct fuse_pollhandle *ph)
|
struct fuse_pollhandle *ph)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_cli_t *tty_cli = (ttynvt_cli_t *) (uintptr_t) info->fh;
|
||||||
|
ttynvt_t *tty = tty_cli->tty;
|
||||||
int revents = 0;
|
int revents = 0;
|
||||||
|
|
||||||
DBG2("%s: tty->pollin=%d tty->error/epipe=%d/%d\n",
|
DBG2("%s (%d): tty->pollin=%d tty->error/epipe=%d/%d\n",
|
||||||
__func__, tty->pollin, tty->error, tty->epipe);
|
__func__, tty_cli->id, tty->pollin, tty->error, tty->epipe);
|
||||||
|
|
||||||
_update_notify(tty, ph);
|
_update_notify(tty, ph);
|
||||||
|
|
||||||
@@ -1097,16 +1160,38 @@ ttynvt_poll(fuse_req_t req, struct fuse_file_info *info,
|
|||||||
|
|
||||||
static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
||||||
{
|
{
|
||||||
ttynvt_t *tty = (ttynvt_t *) (uintptr_t) info->fh;
|
ttynvt_cli_t *tty_cli = (ttynvt_cli_t *) (uintptr_t) info->fh;
|
||||||
|
ttynvt_t *tty = tty_cli->tty;
|
||||||
|
ttynvt_cli_t *tmp, *prev;
|
||||||
|
|
||||||
DBG("%s\n", __func__);
|
DBG("%s\n", __func__);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&access_lock);
|
||||||
|
|
||||||
|
for (tmp = tty->cli, prev = NULL; tmp; prev = tmp, tmp = tmp->next)
|
||||||
|
if (tmp == tty_cli)
|
||||||
|
{
|
||||||
|
nvt_log(LOG_INFO, "Client release (%d)\n", tmp->id);
|
||||||
|
if (prev)
|
||||||
|
prev->next = tmp->next;
|
||||||
|
else
|
||||||
|
tty->cli = tmp->next;
|
||||||
|
free(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tty->cli)
|
||||||
|
goto out;
|
||||||
|
|
||||||
tty->rel_pending = 1;
|
tty->rel_pending = 1;
|
||||||
|
|
||||||
pthread_cancel(tty->ptid_poll);
|
pthread_cancel(tty->ptid_poll);
|
||||||
pthread_join(tty->ptid_poll, NULL);
|
pthread_join(tty->ptid_poll, NULL);
|
||||||
pthread_mutex_destroy(&tty->tty_lock);
|
pthread_mutex_destroy(&tty->tty_lock);
|
||||||
pthread_mutex_destroy(&tty->poll_lock);
|
pthread_mutex_destroy(&tty->poll_lock);
|
||||||
|
pthread_mutex_destroy(&tty->ioctl_lock);
|
||||||
|
pthread_mutex_destroy(&tty->read_lock);
|
||||||
|
pthread_mutex_destroy(&tty->write_lock);
|
||||||
|
|
||||||
if (ttynvt_param.close_delay_us)
|
if (ttynvt_param.close_delay_us)
|
||||||
_ttynvt_sleep_us(ttynvt_param.close_delay_us);
|
_ttynvt_sleep_us(ttynvt_param.close_delay_us);
|
||||||
@@ -1119,11 +1204,13 @@ static void ttynvt_release(fuse_req_t req, struct fuse_file_info *info)
|
|||||||
fuse_pollhandle_destroy(tty->ph);
|
fuse_pollhandle_destroy(tty->ph);
|
||||||
|
|
||||||
_ttynvt_ctx_destroy(tty);
|
_ttynvt_ctx_destroy(tty);
|
||||||
|
ptty = NULL;
|
||||||
fuse_reply_err(req, 0);
|
|
||||||
|
|
||||||
nvt_log(LOG_INFO, "Disconnected from server: %s\n", ttynvt_param.server);
|
nvt_log(LOG_INFO, "Disconnected from server: %s\n", ttynvt_param.server);
|
||||||
|
|
||||||
|
out:
|
||||||
|
fuse_reply_err(req, 0);
|
||||||
|
|
||||||
pthread_mutex_unlock(&access_lock);
|
pthread_mutex_unlock(&access_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user