mirror of
https://github.com/tmux/tmux.git
synced 2024-12-13 18:38:48 +00:00
Support OS X by moving to gettimeofday(2) and adding poll compat from OpenSSH.
This commit is contained in:
parent
0abb4ca413
commit
33aa931541
8
CHANGES
8
CHANGES
@ -1,3 +1,9 @@
|
|||||||
|
28 August 2008
|
||||||
|
|
||||||
|
* Support OS X/Darwin thanks to bsd-poll.c from OpenSSH. Also convert
|
||||||
|
from clock_gettime(2) to gettimeofday(2) as OS X doesn't support the
|
||||||
|
former; microsecond accuracy will have to be sufficient ;-).
|
||||||
|
|
||||||
07 August 2008
|
07 August 2008
|
||||||
|
|
||||||
* Lose some unused/useless wrapper functions.
|
* Lose some unused/useless wrapper functions.
|
||||||
@ -640,4 +646,4 @@
|
|||||||
(including mutt, emacs). No status bar yet and no key remapping or other
|
(including mutt, emacs). No status bar yet and no key remapping or other
|
||||||
customisation.
|
customisation.
|
||||||
|
|
||||||
$Id: CHANGES,v 1.156 2008-08-07 20:20:49 nicm Exp $
|
$Id: CHANGES,v 1.157 2008-08-28 17:45:23 nicm Exp $
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# $Id: GNUmakefile,v 1.37 2008-07-01 05:43:00 nicm Exp $
|
# $Id: GNUmakefile,v 1.38 2008-08-28 17:45:24 nicm Exp $
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ META?= \002
|
|||||||
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \
|
||||||
xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \
|
xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \
|
||||||
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
|
window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \
|
||||||
key-string.c key-bindings.c resize.c arg.c \
|
key-string.c key-bindings.c resize.c arg.c mode-key.c \
|
||||||
cmd.c cmd-generic.c cmd-string.c \
|
cmd.c cmd-generic.c cmd-string.c \
|
||||||
cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \
|
cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \
|
||||||
cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \
|
cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \
|
||||||
@ -78,9 +78,9 @@ endif
|
|||||||
|
|
||||||
ifeq ($(shell uname),Darwin)
|
ifeq ($(shell uname),Darwin)
|
||||||
INCDIRS+= -Icompat
|
INCDIRS+= -Icompat
|
||||||
SRCS+= compat/strtonum.c
|
SRCS+= compat/strtonum.c compat/bsd-poll.c
|
||||||
CFLAGS+= -DNO_STRTONUM -DNO_SETRESUID -DNO_SETRESGID -DNO_SETPROCTITLE \
|
CFLAGS+= -DNO_STRTONUM -DNO_SETRESUID -DNO_SETRESGID -DNO_SETPROCTITLE \
|
||||||
-DNO_TREE_H
|
-DNO_TREE_H -DBROKEN_POLL
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(shell uname),Linux)
|
ifeq ($(shell uname),Linux)
|
||||||
|
5
NOTES
5
NOTES
@ -59,9 +59,6 @@ There are the following known issues:
|
|||||||
trivial and as most modern vt220-based software terminals support it currently
|
trivial and as most modern vt220-based software terminals support it currently
|
||||||
I have better things to work one. Diffs or ideas how to cleanly emulate cs
|
I have better things to work one. Diffs or ideas how to cleanly emulate cs
|
||||||
are welcome.
|
are welcome.
|
||||||
- Darwin/OS X's poll(2) is broken and doesn't support polling pty(4)s; as tmux
|
|
||||||
makes heavy use of this and there are no suitable alternatives on the
|
|
||||||
platform, Darwin and OS X are unfortunately not supported for the present.
|
|
||||||
|
|
||||||
For debugging, running tmux with -v or -vv will generate server and client log
|
For debugging, running tmux with -v or -vv will generate server and client log
|
||||||
files in the current directory.
|
files in the current directory.
|
||||||
@ -73,4 +70,4 @@ welcome. Please email:
|
|||||||
|
|
||||||
-- Nicholas Marriott <nicm@users.sf.net>
|
-- Nicholas Marriott <nicm@users.sf.net>
|
||||||
|
|
||||||
$Id: NOTES,v 1.35 2008-06-25 19:12:30 nicm Exp $
|
$Id: NOTES,v 1.36 2008-08-28 17:45:24 nicm Exp $
|
||||||
|
2
TODO
2
TODO
@ -34,11 +34,11 @@
|
|||||||
or tailqs? what would be fastest per-char?
|
or tailqs? what would be fastest per-char?
|
||||||
- window splitting?
|
- window splitting?
|
||||||
- c/p is still borken in some ways
|
- c/p is still borken in some ways
|
||||||
- poll(2) is broken on OS X/Darwin, a workaround for this would be nice
|
|
||||||
- different screen model? layers perhaps? hmm
|
- different screen model? layers perhaps? hmm
|
||||||
- better mode features: search, back word, forward word, etc
|
- better mode features: search, back word, forward word, etc
|
||||||
- flags to centre screen in window
|
- flags to centre screen in window
|
||||||
- better terminal emulation (identify, insert mode, some other bits)
|
- better terminal emulation (identify, insert mode, some other bits)
|
||||||
|
- 256 colour terminal support
|
||||||
|
|
||||||
-- For 0.5 --------------------------------------------------------------------
|
-- For 0.5 --------------------------------------------------------------------
|
||||||
|
|
||||||
|
10
arg.c
10
arg.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: arg.c,v 1.4 2008-07-23 22:18:06 nicm Exp $ */
|
/* $Id: arg.c,v 1.5 2008-08-28 17:45:25 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -46,18 +46,18 @@ struct session *
|
|||||||
arg_lookup_session(const char *name)
|
arg_lookup_session(const char *name)
|
||||||
{
|
{
|
||||||
struct session *s, *newest = NULL;
|
struct session *s, *newest = NULL;
|
||||||
struct timespec *ts;
|
struct timeval *tv;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
ts = NULL;
|
tv = NULL;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
if (s == NULL || fnmatch(name, s->name, 0) != 0)
|
if (s == NULL || fnmatch(name, s->name, 0) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ts == NULL || timespeccmp(&s->ts, ts, >)) {
|
if (tv == NULL || timercmp(&s->tv, tv, >)) {
|
||||||
newest = s;
|
newest = s;
|
||||||
ts = &s->ts;
|
tv = &s->tv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: buffer-poll.c,v 1.8 2008-07-01 20:35:16 nicm Exp $ */
|
/* $Id: buffer-poll.c,v 1.9 2008-08-28 17:45:25 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -19,7 +19,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@ -45,8 +44,10 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
|
|||||||
(long) getpid(),
|
(long) getpid(),
|
||||||
pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in));
|
pfd->fd, pfd->revents, BUFFER_USED(out), BUFFER_USED(in));
|
||||||
|
|
||||||
|
#ifndef BROKEN_POLL
|
||||||
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
||||||
return (-1);
|
return (-1);
|
||||||
|
#endif
|
||||||
if (pfd->revents & POLLIN) {
|
if (pfd->revents & POLLIN) {
|
||||||
buffer_ensure(in, BUFSIZ);
|
buffer_ensure(in, BUFSIZ);
|
||||||
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
|
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd-list-sessions.c,v 1.15 2008-06-05 21:25:00 nicm Exp $ */
|
/* $Id: cmd-list-sessions.c,v 1.16 2008-08-28 17:45:25 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -48,6 +48,7 @@ cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
char *tim;
|
char *tim;
|
||||||
u_int i, n;
|
u_int i, n;
|
||||||
|
time_t t;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
@ -57,7 +58,8 @@ cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
n = 0;
|
n = 0;
|
||||||
RB_FOREACH(wl, winlinks, &s->windows)
|
RB_FOREACH(wl, winlinks, &s->windows)
|
||||||
n++;
|
n++;
|
||||||
tim = ctime(&s->ts.tv_sec);
|
t = s->tv.tv_sec;
|
||||||
|
tim = ctime(&t);
|
||||||
*strchr(tim, '\n') = '\0';
|
*strchr(tim, '\n') = '\0';
|
||||||
|
|
||||||
ctx->print(ctx, "%s: %u windows"
|
ctx->print(ctx, "%s: %u windows"
|
||||||
|
10
cmd.c
10
cmd.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: cmd.c,v 1.62 2008-07-19 10:07:50 nicm Exp $ */
|
/* $Id: cmd.c,v 1.63 2008-08-28 17:45:25 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -304,7 +304,7 @@ struct session *
|
|||||||
cmd_current_session(struct cmd_ctx *ctx)
|
cmd_current_session(struct cmd_ctx *ctx)
|
||||||
{
|
{
|
||||||
struct msg_command_data *data = ctx->msgdata;
|
struct msg_command_data *data = ctx->msgdata;
|
||||||
struct timespec *ts;
|
struct timeval *tv;
|
||||||
struct session *s, *newest = NULL;
|
struct session *s, *newest = NULL;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
@ -327,12 +327,12 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ts = NULL;
|
tv = NULL;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
s = ARRAY_ITEM(&sessions, i);
|
||||||
if (s != NULL && (ts == NULL || timespeccmp(&s->ts, ts, >))) {
|
if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) {
|
||||||
newest = ARRAY_ITEM(&sessions, i);
|
newest = ARRAY_ITEM(&sessions, i);
|
||||||
ts = &s->ts;
|
tv = &s->tv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (newest);
|
return (newest);
|
||||||
|
123
compat/bsd-poll.c
Normal file
123
compat/bsd-poll.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/* $Id: bsd-poll.c,v 1.1 2008-08-28 17:45:30 nicm Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #include "includes.h" */
|
||||||
|
#define HAVE_SYS_SELECT_H
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if !defined(HAVE_POLL)
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
# include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "bsd-poll.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A minimal implementation of poll(2), built on top of select(2).
|
||||||
|
*
|
||||||
|
* Only supports POLLIN and POLLOUT flags in pfd.events, and POLLIN, POLLOUT
|
||||||
|
* and POLLERR flags in revents.
|
||||||
|
*
|
||||||
|
* Supports pfd.fd = -1 meaning "unused" although it's not standard.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
||||||
|
{
|
||||||
|
nfds_t i;
|
||||||
|
int saved_errno, ret, fd, maxfd = 0;
|
||||||
|
fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL;
|
||||||
|
size_t nmemb;
|
||||||
|
struct timeval tv, *tvp = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < nfds; i++) {
|
||||||
|
fd = fds[i].fd;
|
||||||
|
if (fd >= FD_SETSIZE) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
maxfd = MAX(maxfd, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
nmemb = howmany(maxfd + 1 , NFDBITS);
|
||||||
|
if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
|
||||||
|
(writefds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
|
||||||
|
(exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) {
|
||||||
|
saved_errno = ENOMEM;
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* populate event bit vectors for the events we're interested in */
|
||||||
|
for (i = 0; i < nfds; i++) {
|
||||||
|
fd = fds[i].fd;
|
||||||
|
if (fd == -1)
|
||||||
|
continue;
|
||||||
|
if (fds[i].events & POLLIN) {
|
||||||
|
FD_SET(fd, readfds);
|
||||||
|
FD_SET(fd, exceptfds);
|
||||||
|
}
|
||||||
|
if (fds[i].events & POLLOUT) {
|
||||||
|
FD_SET(fd, writefds);
|
||||||
|
FD_SET(fd, exceptfds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poll timeout is msec, select is timeval (sec + usec) */
|
||||||
|
if (timeout >= 0) {
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = (timeout % 1000) * 1000;
|
||||||
|
tvp = &tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = select(maxfd + 1, readfds, writefds, exceptfds, tvp);
|
||||||
|
saved_errno = errno;
|
||||||
|
|
||||||
|
/* scan through select results and set poll() flags */
|
||||||
|
for (i = 0; i < nfds; i++) {
|
||||||
|
fd = fds[i].fd;
|
||||||
|
fds[i].revents = 0;
|
||||||
|
if (fd == -1)
|
||||||
|
continue;
|
||||||
|
if (FD_ISSET(fd, readfds)) {
|
||||||
|
fds[i].revents |= POLLIN;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(fd, writefds)) {
|
||||||
|
fds[i].revents |= POLLOUT;
|
||||||
|
}
|
||||||
|
if (FD_ISSET(fd, exceptfds)) {
|
||||||
|
fds[i].revents |= POLLERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (readfds != NULL)
|
||||||
|
free(readfds);
|
||||||
|
if (writefds != NULL)
|
||||||
|
free(writefds);
|
||||||
|
if (exceptfds != NULL)
|
||||||
|
free(exceptfds);
|
||||||
|
if (ret == -1)
|
||||||
|
errno = saved_errno;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
61
compat/bsd-poll.h
Normal file
61
compat/bsd-poll.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* $OpenBSD: poll.h,v 1.11 2003/12/10 23:10:08 millert Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996 Theo de Raadt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OPENBSD ORIGINAL: sys/sys/poll.h */
|
||||||
|
|
||||||
|
#if !defined(HAVE_POLL) && !defined(HAVE_POLL_H)
|
||||||
|
#ifndef _COMPAT_POLL_H_
|
||||||
|
#define _COMPAT_POLL_H_
|
||||||
|
|
||||||
|
typedef struct pollfd {
|
||||||
|
int fd;
|
||||||
|
short events;
|
||||||
|
short revents;
|
||||||
|
} pollfd_t;
|
||||||
|
|
||||||
|
typedef unsigned int nfds_t;
|
||||||
|
|
||||||
|
#define POLLIN 0x0001
|
||||||
|
#define POLLOUT 0x0004
|
||||||
|
#define POLLERR 0x0008
|
||||||
|
#if 0
|
||||||
|
/* the following are currently not implemented */
|
||||||
|
#define POLLPRI 0x0002
|
||||||
|
#define POLLHUP 0x0010
|
||||||
|
#define POLLNVAL 0x0020
|
||||||
|
#define POLLRDNORM 0x0040
|
||||||
|
#define POLLNORM POLLRDNORM
|
||||||
|
#define POLLWRNORM POLLOUT
|
||||||
|
#define POLLRDBAND 0x0080
|
||||||
|
#define POLLWRBAND 0x0100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INFTIM (-1) /* not standard */
|
||||||
|
|
||||||
|
int poll(struct pollfd *, nfds_t, int);
|
||||||
|
#endif /* !_COMPAT_POLL_H_ */
|
||||||
|
#endif /* !HAVE_POLL_H */
|
12
paste.c
12
paste.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: paste.c,v 1.3 2008-06-20 18:45:35 nicm Exp $ */
|
/* $Id: paste.c,v 1.4 2008-08-28 17:45:26 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -17,9 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -108,8 +108,8 @@ paste_add(struct paste_stack *ps, const char *data, u_int limit)
|
|||||||
ARRAY_INSERT(ps, 0, pb);
|
ARRAY_INSERT(ps, 0, pb);
|
||||||
|
|
||||||
pb->data = xstrdup(data);
|
pb->data = xstrdup(data);
|
||||||
if (clock_gettime(CLOCK_REALTIME, &pb->ts) != 0)
|
if (gettimeofday(&pb->tv, NULL) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("gettimeofday");
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -124,8 +124,8 @@ paste_replace(struct paste_stack *ps, u_int idx, const char *data)
|
|||||||
xfree(pb->data);
|
xfree(pb->data);
|
||||||
|
|
||||||
pb->data = xstrdup(data);
|
pb->data = xstrdup(data);
|
||||||
if (clock_gettime(CLOCK_REALTIME, &pb->ts) != 0)
|
if (gettimeofday(&pb->tv, NULL) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("gettimeofday");
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
16
server-fn.c
16
server-fn.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: server-fn.c,v 1.49 2008-06-22 22:28:33 nicm Exp $ */
|
/* $Id: server-fn.c,v 1.50 2008-08-28 17:45:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -17,9 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@ -27,17 +27,17 @@
|
|||||||
void
|
void
|
||||||
server_set_client_message(struct client *c, const char *msg)
|
server_set_client_message(struct client *c, const char *msg)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timeval tv;
|
||||||
int delay;
|
int delay;
|
||||||
|
|
||||||
delay = options_get_number(&c->session->options, "display-time");
|
delay = options_get_number(&c->session->options, "display-time");
|
||||||
ts.tv_sec = delay / 1000;
|
tv.tv_sec = delay / 1000;
|
||||||
ts.tv_nsec = (delay % 1000) * 1000000L;
|
tv.tv_usec = (delay % 1000) * 1000L;
|
||||||
|
|
||||||
c->message_string = xstrdup(msg);
|
c->message_string = xstrdup(msg);
|
||||||
if (clock_gettime(CLOCK_REALTIME, &c->message_timer) != 0)
|
if (gettimeofday(&c->message_timer, NULL) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("gettimeofday");
|
||||||
timespecadd(&c->message_timer, &ts, &c->message_timer);
|
timeradd(&c->message_timer, &tv, &c->message_timer);
|
||||||
|
|
||||||
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
|
19
server.c
19
server.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: server.c,v 1.77 2008-06-29 07:04:30 nicm Exp $ */
|
/* $Id: server.c,v 1.78 2008-08-28 17:45:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -197,8 +196,10 @@ server_main(const char *srv_path, int srv_fd)
|
|||||||
log_debug("poll returned %d", nfds);
|
log_debug("poll returned %d", nfds);
|
||||||
|
|
||||||
/* Handle server socket. */
|
/* Handle server socket. */
|
||||||
|
#ifndef BROKEN_POLL
|
||||||
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
|
||||||
fatalx("lost server socket");
|
fatalx("lost server socket");
|
||||||
|
#endif
|
||||||
if (pfd->revents & POLLIN) {
|
if (pfd->revents & POLLIN) {
|
||||||
server_accept_client(srv_fd);
|
server_accept_client(srv_fd);
|
||||||
continue;
|
continue;
|
||||||
@ -377,17 +378,17 @@ void
|
|||||||
server_check_timers(struct client *c)
|
server_check_timers(struct client *c)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct timespec ts, ts2;
|
struct timeval tv, tv2;
|
||||||
u_int interval;
|
u_int interval;
|
||||||
|
|
||||||
if (c == NULL || c->session == NULL)
|
if (c == NULL || c->session == NULL)
|
||||||
return;
|
return;
|
||||||
s = c->session;
|
s = c->session;
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
|
if (gettimeofday(&tv, NULL) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("gettimeofday");
|
||||||
|
|
||||||
if (c->message_string != NULL && timespeccmp(&ts, &c->message_timer, >))
|
if (c->message_string != NULL && timercmp(&tv, &c->message_timer, >))
|
||||||
server_clear_client_message(c);
|
server_clear_client_message(c);
|
||||||
|
|
||||||
if (!options_get_number(&s->options, "status"))
|
if (!options_get_number(&s->options, "status"))
|
||||||
@ -396,9 +397,9 @@ server_check_timers(struct client *c)
|
|||||||
if (interval == 0)
|
if (interval == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(&ts2, &ts, sizeof ts2);
|
memcpy(&tv2, &tv, sizeof tv2);
|
||||||
ts2.tv_sec -= interval;
|
tv2.tv_sec -= interval;
|
||||||
if (timespeccmp(&c->status_timer, &ts2, <))
|
if (timercmp(&c->status_timer, &tv2, <))
|
||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $Id: session.c,v 1.41 2008-06-30 19:11:33 nicm Exp $ */
|
/* $Id: session.c,v 1.42 2008-08-28 17:45:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@ -115,8 +115,8 @@ session_create(const char *name, const char *cmd, u_int sx, u_int sy)
|
|||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
s = xmalloc(sizeof *s);
|
s = xmalloc(sizeof *s);
|
||||||
if (clock_gettime(CLOCK_REALTIME, &s->ts) != 0)
|
if (gettimeofday(&s->tv, NULL) != 0)
|
||||||
fatal("clock_gettime failed");
|
fatal("gettimeofday");
|
||||||
s->curw = s->lastw = NULL;
|
s->curw = s->lastw = NULL;
|
||||||
RB_INIT(&s->windows);
|
RB_INIT(&s->windows);
|
||||||
TAILQ_INIT(&s->alerts);
|
TAILQ_INIT(&s->alerts);
|
||||||
|
12
status.c
12
status.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: status.c,v 1.42 2008-06-27 17:32:24 nicm Exp $ */
|
/* $Id: status.c,v 1.43 2008-08-28 17:45:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -17,10 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -40,14 +40,15 @@ status_redraw(struct client *c)
|
|||||||
size_t size, start, width;
|
size_t size, start, width;
|
||||||
u_char attr, colr;
|
u_char attr, colr;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
time_t t;
|
||||||
int larrow, rarrow;
|
int larrow, rarrow;
|
||||||
|
|
||||||
if (c->sy == 0 || !options_get_number(&s->options, "status"))
|
if (c->sy == 0 || !options_get_number(&s->options, "status"))
|
||||||
goto off;
|
goto off;
|
||||||
larrow = rarrow = 0;
|
larrow = rarrow = 0;
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_REALTIME, &c->status_timer) != 0)
|
if (gettimeofday(&c->status_timer, NULL) != 0)
|
||||||
fatal("clock_gettime failed");
|
fatal("gettimeofday");
|
||||||
colr = options_get_number(&s->options, "status-bg") +
|
colr = options_get_number(&s->options, "status-bg") +
|
||||||
(options_get_number(&s->options, "status-fg") << 4);
|
(options_get_number(&s->options, "status-fg") << 4);
|
||||||
|
|
||||||
@ -55,7 +56,8 @@ status_redraw(struct client *c)
|
|||||||
if (yy == 0)
|
if (yy == 0)
|
||||||
goto blank;
|
goto blank;
|
||||||
|
|
||||||
tm = localtime(&(c->status_timer.tv_sec));
|
t = c->status_timer.tv_sec;
|
||||||
|
tm = localtime(&t);
|
||||||
left = options_get_string(&s->options, "status-left");
|
left = options_get_string(&s->options, "status-left");
|
||||||
strftime(lbuf, sizeof lbuf, left, tm);
|
strftime(lbuf, sizeof lbuf, left, tm);
|
||||||
llen = strlen(lbuf);
|
llen = strlen(lbuf);
|
||||||
|
3
tmux.c
3
tmux.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.c,v 1.73 2008-08-08 17:35:42 nicm Exp $ */
|
/* $Id: tmux.c,v 1.74 2008-08-28 17:45:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -20,7 +20,6 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
45
tmux.h
45
tmux.h
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tmux.h,v 1.181 2008-08-08 17:35:42 nicm Exp $ */
|
/* $Id: tmux.h,v 1.182 2008-08-28 17:45:27 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#define RB_AUGMENT(x) do {} while (0)
|
#define RB_AUGMENT(x) do {} while (0)
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#ifndef NO_QUEUE_H
|
#ifndef NO_QUEUE_H
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
@ -38,9 +39,15 @@
|
|||||||
#include "compat/tree.h"
|
#include "compat/tree.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BROKEN_POLL
|
||||||
|
#include <poll.h>
|
||||||
|
#else
|
||||||
|
#undef HAVE_POLL
|
||||||
|
#include "compat/bsd-poll.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -70,21 +77,21 @@ extern const char *__progname;
|
|||||||
#define __packed __attribute__ ((__packed__))
|
#define __packed __attribute__ ((__packed__))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef timespeccmp
|
#ifndef timercmp
|
||||||
#define timespeccmp(tsp, usp, cmp) \
|
#define timercmp(tvp, uvp, cmp) \
|
||||||
(((tsp)->tv_sec == (usp)->tv_sec) ? \
|
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
||||||
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
|
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
||||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef timespecadd
|
#ifndef timeradd
|
||||||
#define timespecadd(tsp, usp, vsp) \
|
#define timeradd(tvp, uvp, vvp) \
|
||||||
do { \
|
do { \
|
||||||
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
|
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
||||||
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
|
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
||||||
if ((vsp)->tv_nsec >= 1000000000L) { \
|
if ((vvp)->tv_usec >= 1000000) { \
|
||||||
(vsp)->tv_sec++; \
|
(vvp)->tv_sec++; \
|
||||||
(vsp)->tv_nsec -= 1000000000L; \
|
(vvp)->tv_usec -= 1000000; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
@ -616,7 +623,7 @@ struct options {
|
|||||||
/* Paste buffer. */
|
/* Paste buffer. */
|
||||||
struct paste_buffer {
|
struct paste_buffer {
|
||||||
char *data;
|
char *data;
|
||||||
struct timespec ts;
|
struct timeval tv;
|
||||||
};
|
};
|
||||||
ARRAY_DECL(paste_stack, struct paste_buffer *);
|
ARRAY_DECL(paste_stack, struct paste_buffer *);
|
||||||
|
|
||||||
@ -630,7 +637,7 @@ struct session_alert {
|
|||||||
|
|
||||||
struct session {
|
struct session {
|
||||||
char *name;
|
char *name;
|
||||||
struct timespec ts;
|
struct timeval tv;
|
||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
@ -688,7 +695,7 @@ struct tty {
|
|||||||
#define TTY_ESCAPE 0x4
|
#define TTY_ESCAPE 0x4
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct timespec key_timer;
|
struct timeval key_timer;
|
||||||
|
|
||||||
size_t ksize; /* maximum key size */
|
size_t ksize; /* maximum key size */
|
||||||
RB_HEAD(tty_keys, tty_key) ktree;
|
RB_HEAD(tty_keys, tty_key) ktree;
|
||||||
@ -703,7 +710,7 @@ struct client {
|
|||||||
char *title;
|
char *title;
|
||||||
|
|
||||||
struct tty tty;
|
struct tty tty;
|
||||||
struct timespec status_timer;
|
struct timeval status_timer;
|
||||||
|
|
||||||
u_int sx;
|
u_int sx;
|
||||||
u_int sy;
|
u_int sy;
|
||||||
@ -716,7 +723,7 @@ struct client {
|
|||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
char *message_string;
|
char *message_string;
|
||||||
struct timespec message_timer;
|
struct timeval message_timer;
|
||||||
|
|
||||||
char *prompt_string;
|
char *prompt_string;
|
||||||
char *prompt_buffer;
|
char *prompt_buffer;
|
||||||
|
22
tty-keys.c
22
tty-keys.c
@ -1,4 +1,4 @@
|
|||||||
/* $Id: tty-keys.c,v 1.9 2008-07-24 21:42:40 nicm Exp $ */
|
/* $Id: tty-keys.c,v 1.10 2008-08-28 17:45:28 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
@ -17,9 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
@ -299,7 +299,7 @@ tty_keys_next(struct tty *tty, int *code)
|
|||||||
{
|
{
|
||||||
struct tty_key *tk;
|
struct tty_key *tk;
|
||||||
size_t size;
|
size_t size;
|
||||||
struct timespec ts;
|
struct timeval tv;
|
||||||
|
|
||||||
size = BUFFER_USED(tty->in);
|
size = BUFFER_USED(tty->in);
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
@ -324,20 +324,20 @@ tty_keys_next(struct tty *tty, int *code)
|
|||||||
|
|
||||||
/* Escape but no key string. If the timer isn't started, start it. */
|
/* Escape but no key string. If the timer isn't started, start it. */
|
||||||
if (!(tty->flags & TTY_ESCAPE)) {
|
if (!(tty->flags & TTY_ESCAPE)) {
|
||||||
ts.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
ts.tv_nsec = 500 * 1000000L;
|
tv.tv_usec = 500 * 1000L;
|
||||||
if (clock_gettime(CLOCK_REALTIME, &tty->key_timer) != 0)
|
if (gettimeofday(&tty->key_timer, NULL) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("gettimeofday");
|
||||||
timespecadd(&tty->key_timer, &ts, &tty->key_timer);
|
timeradd(&tty->key_timer, &tv, &tty->key_timer);
|
||||||
|
|
||||||
tty->flags |= TTY_ESCAPE;
|
tty->flags |= TTY_ESCAPE;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, if the timer hasn't expired, wait. */
|
/* Otherwise, if the timer hasn't expired, wait. */
|
||||||
if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
|
if (gettimeofday(&tv, NULL) != 0)
|
||||||
fatal("clock_gettime");
|
fatal("gettimeofday");
|
||||||
if (!timespeccmp(&tty->key_timer, &ts, >))
|
if (!timercmp(&tty->key_timer, &tv, >))
|
||||||
return (1);
|
return (1);
|
||||||
tty->flags &= ~TTY_ESCAPE;
|
tty->flags &= ~TTY_ESCAPE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user