34 Commits
Author SHA1 Message Date
Nicolas Viennot edea6cf141 Release 1.8.4 2013-06-14 23:59:26 -04:00
Nicolas Viennot 632553bdc9 SSH log level is tweakable with -v 2013-06-14 23:58:08 -04:00
Nicolas Viennot 7316ed33e1 [libssh] auth: If the agent fails, fall back to regular path
It's causing issues on MacOSX when ssh_agent_get_ident_count()
reports "Agent count: 0".
2013-06-14 23:53:18 -04:00
Nicolas Viennot 8f19552af0 Better error message when SSH keys are not setup 2013-06-14 23:10:24 -04:00
Nicolas Viennot 80f9e84b83 Release 1.8.3 2013-06-14 22:39:28 -04:00
Nicolas Viennot 53355a0b92 Bug fix: $TMUX wasn't being reused properly 2013-06-14 22:39:21 -04:00
Nicolas Viennot 16dd13979e Ubuntu complains without the README 2013-06-14 22:11:13 -04:00
Nicolas Viennot 12d681d8cc Change connection string tmate.io -> master.tmate.io 2013-06-14 22:11:12 -04:00
Nicolas Viennot 5d847fb0aa Random socket path (we don't support multi sessions) 2013-06-14 15:35:39 -04:00
Nicolas Viennot a50dcb09b5 Notification messages 2013-06-13 05:15:08 -04:00
Nicolas Viennot edd194c23c Synchronize copy-mode 2013-06-13 02:34:59 -04:00
Nicolas Viennot fc4eaeb89f TERM defaults to screen-256color 2013-06-13 02:34:58 -04:00
Nicolas Viennot e52312ec3c Report failed commands to slave
which will in turn notify the proper client
2013-06-12 20:33:58 -04:00
Nicolas Viennot 844451c6ce Show tmate messages in the status bar 2013-06-12 19:47:36 -04:00
Nicolas Viennot a1d7bf7dc0 No reconnection for now 2013-06-12 18:02:29 -04:00
Nicolas Viennot 2dca2c0fd5 Synching winlinks idx instead of window ids 2013-06-12 17:58:31 -04:00
Nicolas Viennot e70a5f8b7f Add strack trace debug function 2013-06-12 17:57:53 -04:00
Nicolas Viennot a4e196366e Quick README 2013-06-12 16:30:04 -04:00
Nicolas Viennot 69bc1bfde5 Sync all session windows 2013-06-12 03:19:42 -04:00
Nicolas Viennot bf4edb4056 Authenticating the server 2013-06-12 01:28:01 -04:00
Nicolas Viennot 141428691e Status bar sync 2013-06-11 23:50:16 -04:00
Nicolas Viennot 35daf6d805 Replication of bind/unbind commands 2013-06-11 22:52:21 -04:00
Nicolas Viennot 839c4e3dd9 Replicate remote client commands 2013-06-11 22:32:49 -04:00
Nicolas Viennot b7371802bf Developer Environement setup 2013-06-11 17:00:50 -04:00
Nicolas Viennot f89b98e1c3 Use tmate.io 2013-06-11 13:30:25 -04:00
Nicolas Viennot 6988b99fb4 Enable compression 2013-06-10 05:59:59 -04:00
Nicolas Viennot 56cee30ee8 [libssh] fix server side compression 2013-06-10 05:59:59 -04:00
Nicolas Viennot 7cdb1e2016 [libssh] bug fix in channel_open() 2013-06-10 04:30:12 -04:00
Nicolas Viennot 8131143fa8 gitignore update 2013-06-10 04:30:12 -04:00
Nicolas Viennot a75e70f86b Fix error message 2013-06-10 04:30:12 -04:00
Nicolas Viennot 864124f4c0 Public key auth no longer need to be blocking (libssh 0.6) 2013-06-10 02:50:07 -04:00
Nicolas Viennot 05de59d106 Adding msgpack 2013-06-10 02:50:07 -04:00
Nicolas Viennot 0f7ccda4fb Adding libssh 2013-06-10 02:50:07 -04:00
Nicolas Viennot 220b2afb3c Client side first shot 2013-06-10 01:54:57 -04:00
442 changed files with 76948 additions and 3899 deletions
+4 -2
View File
@@ -6,7 +6,6 @@
core
tags
.deps/
compat/.dirstamp
aclocal.m4
autom4te.cache/
config.log
@@ -16,4 +15,7 @@ tmux
Makefile
Makefile.in
configure
tmux.1.*
tmate
cscope.*
ctags
*.log
+3 -58
View File
@@ -1,58 +1,3 @@
CHANGES FROM 1.8 to 1.9, 20 February 2014
NOTE: This release has bumped the tmux protocol version. It is therefore
advised that the prior tmux server is restarted when this version of tmux is
installed, to avoid protocol mismatch errors for newer clients trying to
talk to an older running tmux server.
Incompatible Changes
====================
* 88 colour support has been removed.
* 'default-path' has been removed. The new-window command accepts '-c' to
cater for this. The previous value of "." can be replaced with: 'neww -c
$PWD', the previous value of '' which meant current path of the pane can
be specified as: 'neww -c "#{pane_current_path}"'
Deprecated Changes
==================
* The single format specifiers: #A -> #Z (where defined) have been
deprecated and replaced with longer-named equivalents, as listed in the
FORMATS section of the tmux manpage.
* The various foo-{fg,bg,attr} commands have been deprecated and replaced
with equivalent foo-style option instead. Currently this is still
backwards-compatible, but will be removed over time.
Normal Changes
==============
* A new environment variable TMUX_TMPDIR is now honoured, allowing the
socket directory to be set outside of TMPDIR (/tmp/ if not set).
* If -s not given to swap-pane the current pane is assumed.
* A #{pane_syncronized} format specifier has been added to be a conditional
format if a pane is in a syncronised mode (c.f. syncronize-panes)
* Tmux now runs under Cygwin natively.
* Formats can now be nested within each other and expanded accordingly.
* Added 'automatic-rename-format' option to allow the automatic rename
mechanism to use something other than the default of
#{pane_current_command}.
* new-session learnt '-c' to specify the starting directory for that session
and all subsequent windows therein.
* The session name is now shown in the message printed to the terminal when
a session is detached.
* Lots more format specifiers have been added.
* Server race conditions have been fixed; in particular commands are not run
until after the configuration file is read completely.
* Case insensitive searching in tmux's copy-mode is now possible.
* attach-session and switch-client learnt the '-t' option to accept a window
and/or a pane to use.
* Copy-mode is only exited if no selection is in progress.
* Paste key in copy-mode is now possible to enter text from the clipboard.
* status-interval set to '0' now works as intended.
* tmux now supports 256 colours running under fbterm.
* Many bug fixes!
CHANGES FROM 1.7 to 1.8, 26 March 2013
Incompatible Changes
@@ -72,7 +17,7 @@ Normal Changes
* run-shell learnt '-t' to specify the pane to use when displaying output.
* Support for middle-click pasting.
* choose-tree learns '-u' to start uncollapsed.
* select-window learnt '-T' to toggle to the last window if it's already
* select-window learnt '-T; to toggle to the last window if it's already
current.
* New session option 'assume-paste-time' for pasting text versus key-binding
actions.
@@ -92,9 +37,9 @@ Normal Changes
the 'source-file' command.
* 'copy-pipe' mode command to copy selection and pipe the selection to a
command.
* Panes can now emit focus notifications for certain applications
* Changes panes can now emit focus notifications for certain applications
which use those.
* run-shell and if-shell now accept formats.
* run-shell and if-shell now accept format placeholders.
* resize-pane learnt '-Z' for zooming a pane temporarily.
* new-session learnt '-A' to make it behave like attach-session.
* set-option learnt '-o' to prevent setting an option which is already set.
-21
View File
@@ -1,21 +0,0 @@
THIS IS FOR INFORMATION ONLY, CODE IS UNDER THE LICENCE AT THE TOP OF ITS FILE.
The README, CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start,
typically:
Copyright (c) <author>
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 MIND, 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.
-39
View File
@@ -396,44 +396,5 @@ configuration file:
Or the default window options:
$ tmux -Lfoo -f/dev/null start\; show -gw
* How do I copy a selection from tmux to the system's clipboard?
When running in xterm(1), tmux can automatically send copied text to the
clipboard. This is controlled by the set-clipboard option and also needs this
X resource to be set:
XTerm*disallowedWindowOps: 20,21,SetXprop
For rxvt-unicode (urxvt), there is an unofficial Perl extension here:
http://anti.teamidiot.de/static/nei/*/Code/urxvt/
Otherwise a key binding for copy mode using xclip (or xsel) works:
bind -temacs-copy C-y copy-pipe "xclip -i >/dev/null"
Or for inside and outside copy mode with the prefix key:
bind C-y run -b "tmux save-buffer - | xclip -i"
On OS X, reattach-to-usernamespace lets pbcopy/pbpaste work:
https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
* Why do I see dots around a session when I attach to it?
tmux limits the size of the window to the smallest attached session. If
it didn't do this then it would be impossible to see the entire window.
The dots mark the size of the window tmux can display.
To avoid this, detach all other clients when attaching:
$ tmux attach -d
Or from inside tmux by detaching individual clients with C-b D or all
using:
C-b : attach -d
$Id$
+49 -60
View File
@@ -1,19 +1,19 @@
# $Id$
# Obvious program stuff.
bin_PROGRAMS = tmux
CLEANFILES = tmux.1.mdoc tmux.1.man
bin_PROGRAMS = tmate
dist_man1_MANS = tmate.1
# Distribution tarball options.
EXTRA_DIST = \
CHANGES FAQ README TODO COPYING examples compat \
array.h compat.h tmux.h osdep-*.c mdoc2man.awk tmux.1
CHANGES FAQ README TODO examples compat \
array.h compat.h tmux.h osdep-*.c
dist-hook:
grep "^#found_debug=" configure
find $(distdir) -name .svn -type d|xargs rm -Rf
# Preprocessor flags.
CPPFLAGS += @XOPEN_DEFINES@ -DTMUX_CONF="\"$(sysconfdir)/tmux.conf\""
CPPFLAGS += @XOPEN_DEFINES@
# glibc as usual does things ass-backwards and hides useful things by default,
# so everyone has to add this.
@@ -21,6 +21,13 @@ if IS_GLIBC
CFLAGS += -D_GNU_SOURCE
endif
CFLAGS += -Wno-unused-parameter -Wno-unused-variable
CFLAGS += -Ilibssh/include/ -Imsgpack/src
if IS_DEVENV
CFLAGS += -DDEVENV
endif
# Set flags for gcc. gcc4 whines abouts silly stuff so it needs slightly
# different flags.
if IS_GCC
@@ -30,8 +37,7 @@ CFLAGS += -O0 -g
CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
CFLAGS += -Wdeclaration-after-statement
CFLAGS += -Wbad-function-cast -Winline -Wcast-align
CPPFLAGS += -DDEBUG
else
CFLAGS += -O2
@@ -48,12 +54,8 @@ endif
# Set flags for Solaris.
if IS_SUNOS
if IS_GCC
CPPFLAGS += -D_XPG6 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
else
CPPFLAGS += -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
endif
endif
# Set flags for Sun CC.
if IS_SUNCC
@@ -61,7 +63,7 @@ CFLAGS += -erroff=E_EMPTY_DECLARATION
endif
# List of sources.
dist_tmux_SOURCES = \
dist_tmate_SOURCES = \
arguments.c \
attributes.c \
cfg.c \
@@ -122,6 +124,7 @@ dist_tmux_SOURCES = \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
cmd-server-info.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-option.c \
@@ -130,6 +133,7 @@ dist_tmux_SOURCES = \
cmd-show-options.c \
cmd-source-file.c \
cmd-split-window.c \
cmd-start-server.c \
cmd-string.c \
cmd-suspend-client.c \
cmd-swap-pane.c \
@@ -173,7 +177,12 @@ dist_tmux_SOURCES = \
session.c \
signal.c \
status.c \
style.c \
tmate-debug.c \
tmate-ssh-client.c \
tmate-encoder.c \
tmate-decoder.c \
tmate-msg.c \
tmate.c \
tmux.c \
tty-acs.c \
tty-keys.c \
@@ -186,85 +195,65 @@ dist_tmux_SOURCES = \
window.c \
xmalloc.c \
xterm-keys.c
nodist_tmux_SOURCES = osdep-@PLATFORM@.c
nodist_tmate_SOURCES = osdep-@PLATFORM@.c
# Pile in all the compat/ stuff that is needed.
if NO_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
nodist_tmate_SOURCES += compat/forkpty-@PLATFORM@.c
endif
if NO_IMSG
nodist_tmux_SOURCES += compat/imsg.c compat/imsg-buffer.c
nodist_tmate_SOURCES += compat/imsg.c compat/imsg-buffer.c
endif
if NO_CLOSEFROM
nodist_tmux_SOURCES += compat/closefrom.c
nodist_tmate_SOURCES += compat/closefrom.c
endif
if NO_DAEMON
nodist_tmux_SOURCES += compat/daemon.c
nodist_tmate_SOURCES += compat/daemon.c
endif
if NO_SETENV
nodist_tmux_SOURCES += compat/setenv.c
nodist_tmate_SOURCES += compat/setenv.c
endif
if NO_STRLCAT
nodist_tmux_SOURCES += compat/strlcat.c
nodist_tmate_SOURCES += compat/strlcat.c
endif
if NO_STRLCPY
nodist_tmux_SOURCES += compat/strlcpy.c
nodist_tmate_SOURCES += compat/strlcpy.c
endif
if NO_ASPRINTF
nodist_tmux_SOURCES += compat/asprintf.c
nodist_tmate_SOURCES += compat/asprintf.c
endif
if NO_FGETLN
nodist_tmux_SOURCES += compat/fgetln.c
nodist_tmate_SOURCES += compat/fgetln.c
endif
if NO_GETOPT
nodist_tmux_SOURCES += compat/getopt.c
nodist_tmate_SOURCES += compat/getopt.c
endif
if NO_STRCASESTR
nodist_tmux_SOURCES += compat/strcasestr.c
nodist_tmate_SOURCES += compat/strcasestr.c
endif
if NO_STRSEP
nodist_tmux_SOURCES += compat/strsep.c
nodist_tmate_SOURCES += compat/strsep.c
endif
if NO_VIS
nodist_tmux_SOURCES += compat/vis.c compat/unvis.c
nodist_tmate_SOURCES += compat/vis.c compat/unvis.c
endif
if NO_STRTONUM
nodist_tmux_SOURCES += compat/strtonum.c
nodist_tmate_SOURCES += compat/strtonum.c
endif
if NO_B64_NTOP
nodist_tmux_SOURCES += compat/b64_ntop.c
endif
if NO_CFMAKERAW
nodist_tmux_SOURCES += compat/cfmakeraw.c
endif
if NO_OPENAT
nodist_tmux_SOURCES += compat/openat.c
nodist_tmate_SOURCES += compat/b64_ntop.c
endif
# Install tmux.1 in the right format.
install-exec-hook:
if test x@MANFORMAT@ = xmdoc; then \
sed -e "s|@SYSCONFDIR@|$(sysconfdir)|g" $(srcdir)/tmux.1 \
>$(srcdir)/tmux.1.mdoc; \
else \
sed -e "s|@SYSCONFDIR@|$(sysconfdir)|g" $(srcdir)/tmux.1| \
$(AWK) -fmdoc2man.awk >$(srcdir)/tmux.1.man; \
fi
$(MKDIR_P) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/tmux.1.@MANFORMAT@ \
$(DESTDIR)$(mandir)/man1/tmux.1
tmate_LDADD = \
libssh/build/src/libssh.a \
msgpack/src/.libs/libmsgpackc.a
# Update SF web site.
upload-index.html: update-index.html
scp www/index.html www/main.css www/images/*.png \
${USER},tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
rm -f www/index.html www/images/small-*
*.c: $(tmate_LDADD)
update-index.html:
(cd www/images && \
rm -f small-* && \
for i in *.png; do \
convert "$$i" -resize 200x150 "small-$$i"; \
done \
)
sed "s/%%VERSION%%/${VERSION}/g" www/index.html.in >www/index.html
libssh/build/src/libssh.a:
cd libssh/build && cmake .. -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_PCAP=OFF -DWITH_STATIC_LIB=ON
+make -C libssh/build ssh_static
msgpack/src/.libs/libmsgpackc.a:
cd msgpack && ./bootstrap && ./configure
+make -C msgpack/src libmsgpackc.la
-60
View File
@@ -1,60 +0,0 @@
Welcome to tmux!
tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
to be accessed and controlled from a single terminal. tmux is intended to be a
simple, modern, BSD-licensed alternative to programs such as GNU screen.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
run on Solaris and AIX (although they haven't been tested in a while).
tmux depends on libevent 2.x. Download it from:
http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
To get and build the latest from version control:
$ git clone git://git.code.sf.net/p/tmux/tmux-code tmux
$ cd tmux
$ sh autogen.sh
$ ./configure && make
For more information see https://sourceforge.net/scm/?type=git&group_id=200378
and http://git-scm.com. Patches should be sent by email to the mailing list at
tmux-users@lists.sourceforge.net.
For documentation on using tmux, see the tmux.1 manpage. It can be viewed from
the source tree with:
$ nroff -mdoc tmux.1|less
Some common questions are answered in the FAQ file and a more extensive (but
slightly out of date) guide is available in the OpenBSD FAQ at
http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
file and some example configurations and a Vim syntax file are in the examples
directory.
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
tmux mailing lists are available. Visit:
https://sourceforge.net/mail/?group_id=200378
Bug reports, feature suggestions and especially code contributions are most
welcome. Please send by email to:
tmux-users@lists.sourceforge.net
This file and the CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start.
-- Nicholas Marriott <nicm@users.sf.net>
$Id$
Symlink
+1
View File
@@ -0,0 +1 @@
README.md
+60
View File
@@ -0,0 +1,60 @@
Welcome to tmux!
tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
to be accessed and controlled from a single terminal. tmux is intended to be a
simple, modern, BSD-licensed alternative to programs such as GNU screen.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
run on Solaris and AIX (although they haven't been tested in a while).
Since the 1.2 release tmux depends on libevent. Download it from:
http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
To get and build the latest from version control:
$ git clone git://git.code.sf.net/p/tmux/tmux-code tmux
$ cd tmux
$ sh autogen.sh
$ ./configure && make
For more information see https://sourceforge.net/scm/?type=git&group_id=200378
and http://git-scm.com. Patches should be sent by email to the mailing list at
tmux-users@lists.sourceforge.net.
For documentation on using tmux, see the tmux.1 manpage. It can be viewed from
the source tree with:
$ nroff -mdoc tmux.1|less
Some common questions are answered in the FAQ file and a more extensive (but
slightly out of date) guide is available in the OpenBSD FAQ at
http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
file and some example configurations and a Vim syntax file are in the examples
directory.
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
tmux mailing lists are available. Visit:
https://sourceforge.net/mail/?group_id=200378
Bug reports, feature suggestions and especially code contributions are most
welcome. Please send by email to:
tmux-users@lists.sourceforge.net
This file and the CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start.
-- Nicholas Marriott <nicm@users.sf.net>
$Id$
+33
View File
@@ -0,0 +1,33 @@
tmate
=====
What is it?
-----------
Tmate is a fork of tmux. It provides an instant pairing solution.
License
-------
tmate is built on top of tmux, libssh and msgpack. Their respective licenses are
in the sources. tmate is MIT licensed.
Copyright (c) 2013 Nicolas Viennot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+147 -125
View File
@@ -1,133 +1,155 @@
- command bits and pieces:
* use "--" to mark start of command w/ neww etc to avoid quoting
* why doesn't command-prompt work if made read-only?
* allow multiple targets: fnmatch for -t/-c, for example detach all
clients with -t*
* add -c for new-session like new-window
* attach should take a pane and select it as well as attaching
* ' and " should be parsed the same (eg "\e" vs '\e') in config
and command prompt
* last-pane across sessions
* exact match operator for targets (or break the substring match
and require eg x* instead of just x)
NOTES
=====
- make command sequences more usable
* don't require space after ;
* options for error handling: && and ||?
This file describes rough notes regarding ideas for potential future tmux
development. It's not necessarily guaranteed that items in this TODO file
will ever get implemented.
- options bits and pieces:
* set-remain-on-exit is a complete hack
* way to set socket path from config file
It is asked therefore, that anyone thinking of undertaking a task in this
TODO file, email tmux-users@lists.sf.net to discuss the feature.
- format improvements:
* option to quote format (#{session_name:quoted})
* formats need conditions for >0 (for #P)
* some way to pad # stuff with spaces, #!2T maybe
* status stuff is redundant with formats
* last window update time and format for it
* formats to show if a window is linked into multiple sessions, into
multiple attached sessions, and is the active window in multiple
attached sessions?
Thie file is split up between tmux user interface (UI) issues, and terminal
compatibility issues.
- choose mode improvements:
* choose-pane command (augment choose-tree to do this?)
* choose-mode and copy-mode are very similar, make choose-mode a subset?
* flag to choose-* for sort order
* choose mode would be better per client than per window
* two choices (first one then second, for swap-pane and join-pane)
- improve monitor-*:
* straighten out rules for multiple clients
* think about what happens across sessions
* monitor changes within a region
* perhaps monitor /all/ panes in the window not just one
- improve mouse support:
* bind commands to mouse in different areas?
* more fine-grained options
* commands executed when clicking on a pattern (URL)
* send arrow key sequences for mouse scroll wheel in alternate screen
* mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets
the flag on w/o checking the others before calling tty_update_mode)
- hooks!
TMUX UI ISSUES
==============
- implicitly add exec to the commands for new windows (switch to disable it)?
- bring back detach-session to detach all clients on a session?
- allow fnmatch for -c, so that you can, eg, detach all clients
- garbage collect window history (100 lines at a time?) if it hasn't been used
in $x time
- flags to centre screen in window
- activity/bell should be per-window not per-link? what if it is cur win in
session not being watched?
- should be able to move to a hidden pane and it would be moved into view. pane
number in status line/top-right would be cool for this
- support other mouse modes (highlight etc) and use it in copy mode
- set-remain-on-exit is a bit of a hack, some way to do it generically?
- would be nice to be able to use "--" to mark start of command w/ neww etc
to avoid quoting
- make command sequences more usable: don't require space after ;, handle
errors better
- choice and more mode would be better per client than per window?
- hooks to which commands may be attached, for example: tmux add-hook
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
$HOME/.tmux-session.conf
- way to set socket path from config file
- warts on current naming:
* display-time but message-fg/bg/attr
* list-* vs show-*
* split-window -> split-pane??
- better UTF-8 support:
* #22T can split in the middle of UTF-8 characters!
* window names and titles
* message display
* prompt input
* multibyte key input
* buffer_sample and the choose-* could show UTF-8 properly
- copy/paste improvements:
* incremental searching
* append to buffer
* paste w/o trailing whitespace
* named buffers and allow gaps in the stack
* command to toggle selection not to move it in copy-mode
- layout stuff
* way to tag a layout as a number/name
* maybe keep last layout + size around and if size reverts just put it
back
* revamp layouts: they are too complicated, should be more closely
integrated, should support hints, layout sets should just be a
special case of custom layouts, and we should support panes that are
not attached to a cell at all. this could be the time to introduce
panelink to replace layout_cell
* way to set hints/limits about pane size for resizing
* panning over window (window larger than visible)
- terminfo bits
* use a better termcap internally instead of screen, perhaps xterm
* use screen-256color when started on 256 colour terminal?
* need a tmux terminfo entry to document the extensions we are using in
upstream terminfo
* support title stack, both internally and externally (restore on
detach) http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- code cleanup
* instead of separate window and session options, just one master
options list with each option having a type (window or session), then
options on window, on session, and global. for window options we look
window->session->global, and for session we look session->global
* the way pane, window, session destroy is handled is too complicated
and the distinction between session.c, window.c and server-fn.c
functions is not clear. could we just have kill_pane(),
kill_window(), unlink_window(), kill_session() that fix up all data
structures (flagging sessions as dead) and return a value to say
whether clients need to be checked for dead sessions? sort of like
session_detach now but more so. or some other scheme to make it
simpler and clearer? also would be nice to remove/rename server-fn.c
* more readable way to work out the various things commands need to
know about the client, notably:
- is this the config file? (cmdq->c == NULL)
- is this a command client? (cmdq->c != NULL &&
cmdq->c->session == NULL)
- is this a control client?
- can i do stdin or stdout to this client?
or even guarantee that cmdq->c != NULL and provide a better way to
tell when in the config file - then we use cmdq->c if we need a
client w/o a session else cmd_current_client
* optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
- miscellaneous
* way to keep a job running just read its last line of output for #()
link panes into multiple windows
* live update: server started with -U connects to server, requests
sessions and windows, receives file descriptors
* there are inconsistencies in what we get from old shell and what
comes from config for new sessions and windows
* multiline status line?
* bind commands to key sequences -- make it so ALL keys go through a
table, first an implicit table in which C-b is the only default
binding to a command that says "next key from $othertable" and so
on. means -n can go away as well
- display-time but message-fg/bg/attr
- list-* vs show-*
- server-info
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
- split-window -> split-pane??
- some way to force a screen to use the entire terminal even if it is forced
to be smaller by other clients. pan smaller terminal? (like screen F)
-- idea of a "view" onto a window, need base x/y offsets for redraw
- commands should be able to succeed or fail and have || or && for command
lists
- some way to keep a command running continually and just use its last line of
output
- UTF-8 to a non-UTF-8 terminal should not be able to balls up
the terminal - www/ruby-addressable; make regress
- support esc-esc to quit in modes
- fix ctrl+F1-F4 output. to what?
- better utf8 support: window names, prompt input, message display
- option to move copy mode indicator into status line
- selection behaviour closer to vi in vi mode
- live update: server started with -U connects to server, requests sessions and
windows, receives fds
- sort out inheriting config from shell on new sessions/windows:
should pick up default-path/termios/etc from client if possible,
else leave empty/default
- link panes into multiple windows
- bells should be passed between sessions with visual-bell etc
sequence until its shell exits, to allow them to be used from the config file
- better session sharing: create-socket command to create socket somewhere (-r
flag for readonly)
- multiline status line (no?)
- support title stack, both internally and externally
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- some way to pad # stuff with spaces, #!2T maybe
- a binding to "scroll down and exit at bottom" copy mode
- some way to pass keystrokes in copy mode through to underlying window. why?
- last window update time and # replacement for it for display-message
- find-window across sessions - other ways to make session handling easier?
- ' and " should be parsed the same (eg "\e" vs '\e') in config and command
prompt?
- command to toggle selection not to move it in copy-mode
- audit of escape sequence support vs xterm
- support binding keys to mouse (mouse-select-pane -> mouse-keys or something,
mouse click == select-pane -t %%, mouse scroll up == copy-mode)
- bind commands to key sequences? -- make it so ALL keys go through a table,
first an implicit table in which C-b is the only default binding to a
command that says "next key from $othertable" and so on. means -n can
go away as well
- monitor, bell etc should monitor /all/ panes in the window not just one
- a history of commands that can be reversed (reverse member of each command,
and a buffer)
- info() when changing to same window
- way to add dest for break-pane; maybe some easier way to unbreak-pane
- case insensitive searching
- incremental searching in copy mode.
- configurable borders and empty space filler for when panes < window?
- mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets the
flag on w/o checking the others before calling tty_update_mode)
- pass shell commands as argv rather than strings, allow them to be specified
in commands without quotes
- named buffers and allow gaps in the stack
- monitor-activity is broken in several ways with multiple clients
- monitor-activity should be more powerful (eg set a region)
- maybe a way to put pane names instead of window names in status line
- support for borderless panes
- wait-for command 20130222153957.GY6782@yelena.nicm.ath.cx
- last-pane across sessions
- panes should have names like windows
- command-prompt doesn't work if made read-only. why?
- option to quote format eg #{session_name:quoted}
- formats need conditions for >0 (for #P)
- fetch full command line on !Linux, and add option to strip prefixes
such as "sh " "/bin/sh " etc etc
- synchronize-windows option
- append to buffer in copy mode
- way to paste w/o trailing whitespace
- flag to switch-client to switch all clients
- history of layouts and undo/redo flags to selectl
- way to tag a layout as a number/name
- optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
- support multibyte key strings
- allow commands to be executed when certain patterns in a screen
are clicked on with the mouse
- flag to make next/previous commands skip a window
- way to do tmux command/run-shell from mode keys
- send command to all windows
- choose-pane command (augment choose-tree to do this?)
- choose-mode and copy-mode are very similar. Perhaps make choose-mode a subset
of copy-mode in that it inherits key-bindings and other traits but not all
- add -c for new-session like new-window
- flag to choose-* for sort order (eg sort windows/sessions/clients by last
used time) - perhaps using formats (but what about numeric sort)?
- instead of separate window and session options, just one master options list
with each option having a type (window or session), then options on window,
on session, and global. for window options we look window->session->global,
and for session we look session->global
- maybe keep last layout + size around and if size reverts just put it back
- way to set hints/limits about pane size for resizing
- revamp layouts: they are too complicated, should be more closely integrated,
should support hints, layout sets should just be a special case of custom
layouts, and we should support panes that are not attached to a cell at
all. this could be the time to introduce panelink to replace layout_cell
- run-shell/if-shell should support formats
- attach should take a pane and select it as well as attaching
- attach should have a flag to create session if it doesn't exist. or better
new a flag to attach it
TERMINAL ISSUES
================
- use a better termcap internally instead of screen, perhaps xterm
- clear window title on exit (see using xterm title stack)
- get it passing all the vttest tests that don't require resizing the terminal
- support for bce
- use screen-256color when started on 256 colour terminal?
* We need a tmux terminfo entry to document the extensions we are using in
upstream terminfo. Must NOT change (only add or remove) anything from
TERM=screen so we can fallback!
+43 -76
View File
@@ -20,25 +20,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
/*
* Manipulate command arguments.
*/
struct args_entry *args_find(struct args *, u_char);
RB_GENERATE(args_tree, args_entry, entry, args_cmp);
/* Arguments tree comparison function. */
int
args_cmp(struct args_entry *a1, struct args_entry *a2)
{
return (a1->flag - a2->flag);
}
/* Create an arguments set with no flags. */
struct args *
args_create(int argc, ...)
@@ -48,6 +32,8 @@ args_create(int argc, ...)
int i;
args = xcalloc(1, sizeof *args);
if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
fatal("bit_alloc failed");
args->argc = argc;
if (argc == 0)
@@ -63,36 +49,35 @@ args_create(int argc, ...)
return (args);
}
/* Find a flag in the arguments tree. */
struct args_entry *
args_find(struct args *args, u_char ch)
{
struct args_entry entry;
entry.flag = ch;
return (RB_FIND(args_tree, &args->tree, &entry));
}
/* Parse an argv and argc into a new argument set. */
struct args *
args_parse(const char *template, int argc, char **argv)
{
struct args *args;
char *ptr;
int opt;
args = xcalloc(1, sizeof *args);
if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
fatal("bit_alloc failed");
optreset = 1;
optind = 1;
while ((opt = getopt(argc, argv, template)) != -1) {
if (opt < 0)
if (opt < 0 || opt >= SCHAR_MAX)
continue;
if (opt == '?' || strchr(template, opt) == NULL) {
args_free(args);
if (opt == '?' || (ptr = strchr(template, opt)) == NULL) {
free(args->flags);
free(args);
return (NULL);
}
args_set(args, opt, optarg);
bit_set(args->flags, opt);
if (ptr[1] == ':') {
free(args->values[opt]);
args->values[opt] = xstrdup(optarg);
}
}
argc -= optind;
argv += optind;
@@ -107,17 +92,14 @@ args_parse(const char *template, int argc, char **argv)
void
args_free(struct args *args)
{
struct args_entry *entry;
struct args_entry *entry1;
u_int i;
cmd_free_argv(args->argc, args->argv);
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
RB_REMOVE(args_tree, &args->tree, entry);
free(entry->value);
free(entry);
}
for (i = 0; i < SCHAR_MAX; i++)
free(args->values[i]);
free(args->flags);
free(args);
}
@@ -125,10 +107,9 @@ args_free(struct args *args)
size_t
args_print(struct args *args, char *buf, size_t len)
{
size_t off;
int i;
const char *quotes;
struct args_entry *entry;
size_t off;
int i;
const char *quotes;
/* There must be at least one byte at the start. */
if (len == 0)
@@ -137,23 +118,23 @@ args_print(struct args *args, char *buf, size_t len)
/* Process the flags first. */
buf[off++] = '-';
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->value != NULL)
for (i = 0; i < SCHAR_MAX; i++) {
if (!bit_test(args->flags, i) || args->values[i] != NULL)
continue;
if (off == len - 1) {
buf[off] = '\0';
return (len);
}
buf[off++] = entry->flag;
buf[off++] = i;
buf[off] = '\0';
}
if (off == 1)
buf[--off] = '\0';
/* Then the flags with arguments. */
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->value == NULL)
for (i = 0; i < SCHAR_MAX; i++) {
if (!bit_test(args->flags, i) || args->values[i] == NULL)
continue;
if (off >= len) {
@@ -161,13 +142,12 @@ args_print(struct args *args, char *buf, size_t len)
return (len);
}
if (strchr(entry->value, ' ') != NULL)
if (strchr(args->values[i], ' ') != NULL)
quotes = "\"";
else
quotes = "";
off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
off != 0 ? " " : "", entry->flag, quotes, entry->value,
quotes);
off != 0 ? " " : "", i, quotes, args->values[i], quotes);
}
/* And finally the argument vector. */
@@ -192,55 +172,42 @@ args_print(struct args *args, char *buf, size_t len)
int
args_has(struct args *args, u_char ch)
{
return (args_find(args, ch) == NULL ? 0 : 1);
return (bit_test(args->flags, ch));
}
/* Set argument value in the arguments tree. */
/* Set argument value. */
void
args_set(struct args *args, u_char ch, const char *value)
{
struct args_entry *entry;
/* Replace existing argument. */
if ((entry = args_find(args, ch)) != NULL) {
free(entry->value);
entry->value = NULL;
} else {
entry = xcalloc(1, sizeof *entry);
entry->flag = ch;
RB_INSERT(args_tree, &args->tree, entry);
}
free(args->values[ch]);
if (value != NULL)
entry->value = xstrdup(value);
args->values[ch] = xstrdup(value);
else
args->values[ch] = NULL;
bit_set(args->flags, ch);
}
/* Get argument value. Will be NULL if it isn't present. */
const char *
args_get(struct args *args, u_char ch)
{
struct args_entry *entry;
if ((entry = args_find(args, ch)) == NULL)
return (NULL);
return (entry->value);
return (args->values[ch]);
}
/* Convert an argument value to a number. */
long long
args_strtonum(struct args *args, u_char ch, long long minval, long long maxval,
char **cause)
args_strtonum(struct args *args,
u_char ch, long long minval, long long maxval, char **cause)
{
const char *errstr;
long long ll;
struct args_entry *entry;
const char *errstr;
long long ll;
if ((entry = args_find(args, ch)) == NULL) {
if (!args_has(args, ch)) {
*cause = xstrdup("missing");
return (0);
}
ll = strtonum(entry->value, minval, maxval, &errstr);
ll = strtonum(args->values[ch], minval, maxval, &errstr);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);
-15
View File
@@ -31,7 +31,6 @@ struct cmd_q *cfg_cmd_q;
int cfg_finished;
int cfg_references;
struct causelist cfg_causes;
struct client *cfg_client;
int
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
@@ -128,20 +127,6 @@ cfg_default_done(unused struct cmd_q *cmdq)
cmdq_free(cfg_cmd_q);
cfg_cmd_q = NULL;
if (cfg_client != NULL) {
/*
* The client command queue starts with client_exit set to 1 so
* only continue if not empty (that is, we have been delayed
* during configuration parsing for long enough that the
* MSG_COMMAND has arrived), else the client will exit before
* the MSG_COMMAND which might tell it not to.
*/
if (!TAILQ_EMPTY(&cfg_client->cmdq->queue))
cmdq_continue(cfg_client->cmdq);
cfg_client->references--;
cfg_client = NULL;
}
}
void
+103 -134
View File
@@ -48,14 +48,13 @@ enum {
} client_exitreason = CLIENT_EXIT_NONE;
int client_exitval;
enum msgtype client_exittype;
const char *client_exitsession;
int client_attached;
int client_get_lock(char *);
int client_connect(char *, int);
void client_send_identify(int);
int client_write_one(enum msgtype, int, const void *, size_t);
int client_write_server(enum msgtype, const void *, size_t);
void client_send_environ(void);
void client_write_server(enum msgtype, void *, size_t);
void client_update_event(void);
void client_signal(int, short, void *);
void client_stdin_callback(int, short, void *);
@@ -79,8 +78,8 @@ client_get_lock(char *lockfile)
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1)
fatal("open failed");
if (lockf(lockfd, F_TLOCK, 0) == -1 && errno == EAGAIN) {
while (lockf(lockfd, F_LOCK, 0) == -1 && errno == EINTR)
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) {
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
/* nothing */;
close(lockfd);
return (-1);
@@ -118,15 +117,10 @@ retry:
close(fd);
xasprintf(&lockfile, "%s.lock", path);
if ((lockfd = client_get_lock(lockfile)) == -1) {
free(lockfile);
if ((lockfd = client_get_lock(lockfile)) == -1)
goto retry;
}
if (unlink(path) != 0 && errno != ENOENT) {
free(lockfile);
close(lockfd);
if (unlink(path) != 0 && errno != ENOENT)
return (-1);
}
fd = server_start(lockfd, lockfile);
free(lockfile);
close(lockfd);
@@ -144,24 +138,12 @@ failed:
const char *
client_exit_message(void)
{
static char msg[256];
switch (client_exitreason) {
case CLIENT_EXIT_NONE:
break;
case CLIENT_EXIT_DETACHED:
if (client_exitsession != NULL) {
xsnprintf(msg, sizeof msg, "detached "
"(from session %s)", client_exitsession);
return (msg);
}
return ("detached");
case CLIENT_EXIT_DETACHED_HUP:
if (client_exitsession != NULL) {
xsnprintf(msg, sizeof msg, "detached and SIGHUP "
"(from session %s)", client_exitsession);
return (msg);
}
return ("detached and SIGHUP");
case CLIENT_EXIT_LOST_TTY:
return ("lost tty");
@@ -183,13 +165,12 @@ client_main(int argc, char **argv, int flags)
{
struct cmd *cmd;
struct cmd_list *cmdlist;
struct msg_command_data *data;
int cmdflags, fd, i;
struct msg_command_data cmddata;
int cmdflags, fd;
pid_t ppid;
enum msgtype msg;
char *cause;
struct termios tio, saved_tio;
size_t size;
/* Set up the initial command. */
cmdflags = 0;
@@ -198,7 +179,7 @@ client_main(int argc, char **argv, int flags)
cmdflags = CMD_STARTSERVER;
} else if (argc == 0) {
msg = MSG_COMMAND;
cmdflags = CMD_STARTSERVER|CMD_CANTNEST;
cmdflags = CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
} else {
msg = MSG_COMMAND;
@@ -216,6 +197,8 @@ client_main(int argc, char **argv, int flags)
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (cmd->entry->flags & CMD_STARTSERVER)
cmdflags |= CMD_STARTSERVER;
if (cmd->entry->flags & CMD_SENDENVIRON)
cmdflags |= CMD_SENDENVIRON;
if (cmd->entry->flags & CMD_CANTNEST)
cmdflags |= CMD_CANTNEST;
}
@@ -237,8 +220,7 @@ client_main(int argc, char **argv, int flags)
/* Initialise the client socket and start the server. */
fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
if (fd == -1) {
fprintf(stderr, "failed to connect to server: %s\n",
strerror(errno));
fprintf(stderr, "failed to connect to server\n");
return (1);
}
@@ -256,7 +238,7 @@ client_main(int argc, char **argv, int flags)
setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
client_stdin_callback, NULL);
if (flags & CLIENT_CONTROLCONTROL) {
if (flags & IDENTIFY_TERMIOS) {
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
fprintf(stderr, "tcgetattr failed: %s\n",
strerror(errno));
@@ -279,33 +261,26 @@ client_main(int argc, char **argv, int flags)
/* Establish signal handlers. */
set_signals(client_signal);
/* Send identify messages. */
/* Send initial environment. */
if (cmdflags & CMD_SENDENVIRON)
client_send_environ();
client_send_identify(flags);
/* Send first command. */
if (msg == MSG_COMMAND) {
/* How big is the command? */
size = 0;
for (i = 0; i < argc; i++)
size += strlen(argv[i]) + 1;
data = xmalloc((sizeof *data) + size);
/* Fill in command line arguments. */
cmddata.pid = environ_pid;
cmddata.session_id = environ_session_id;
/* Prepare command for server. */
data->argc = argc;
if (cmd_pack_argv(argc, argv, (char*)(data + 1), size) != 0) {
cmddata.argc = argc;
if (cmd_pack_argv(
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
fprintf(stderr, "command too long\n");
free(data);
return (1);
}
size += sizeof *data;
/* Send the command. */
if (client_write_server(msg, data, size) != 0) {
fprintf(stderr, "failed to send command\n");
free(data);
return (1);
}
free(data);
client_write_server(msg, &cmddata, sizeof cmddata);
} else if (msg == MSG_SHELL)
client_write_server(msg, NULL, 0);
@@ -321,75 +296,65 @@ client_main(int argc, char **argv, int flags)
ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP);
} else if (flags & CLIENT_CONTROLCONTROL) {
if (client_exitreason != CLIENT_EXIT_NONE)
printf("%%exit %s\n", client_exit_message());
else
printf("%%exit\n");
printf("\033\\");
} else if (flags & IDENTIFY_TERMIOS) {
if (flags & IDENTIFY_CONTROL) {
if (client_exitreason != CLIENT_EXIT_NONE)
printf("%%exit %s\n", client_exit_message());
else
printf("%%exit\n");
printf("\033\\");
}
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
}
setblocking(STDIN_FILENO, 1);
return (client_exitval);
}
/* Send identify messages to server. */
/* Send identify message to server with the file descriptors. */
void
client_send_identify(int flags)
{
const char *s;
char **ss;
int fd;
struct msg_identify_data data;
char *term;
int fd;
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
data.flags = flags;
if ((s = getenv("TERM")) == NULL)
s = "";
client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
*data.cwd = '\0';
if ((s = ttyname(STDIN_FILENO)) == NULL)
s = "";
client_write_one(MSG_IDENTIFY_TTYNAME, -1, s, strlen(s) + 1);
if ((fd = open(".", O_RDONLY)) == -1)
fd = open("/", O_RDONLY);
client_write_one(MSG_IDENTIFY_CWD, fd, NULL, 0);
term = getenv("TERM");
if (term == NULL ||
strlcpy(data.term, term, sizeof data.term) >= sizeof data.term)
*data.term = '\0';
if ((fd = dup(STDIN_FILENO)) == -1)
fatal("dup failed");
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
for (ss = environ; *ss != NULL; ss++)
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0);
imsg_compose(&client_ibuf,
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
client_update_event();
}
/* Helper to send one message. */
int
client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
/* Forward entire environment to server. */
void
client_send_environ(void)
{
int retval;
struct msg_environ_data data;
char **var;
retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd,
(void*)buf, len);
if (retval != 1)
return (-1);
return (0);
for (var = environ; *var != NULL; var++) {
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
continue;
client_write_server(MSG_ENVIRON, &data, sizeof data);
}
}
/* Write a message to the server without a file descriptor. */
int
client_write_server(enum msgtype type, const void *buf, size_t len)
void
client_write_server(enum msgtype type, void *buf, size_t len)
{
int retval;
retval = client_write_one(type, -1, buf, len);
if (retval == 0)
client_update_event();
return (retval);
imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
client_update_event();
}
/* Update client event based on whether it needs to read or read and write. */
@@ -474,7 +439,7 @@ client_callback(unused int fd, short events, void *data)
}
if (events & EV_WRITE) {
if (msgbuf_write(&client_ibuf.w) < 0 && errno != EAGAIN)
if (msgbuf_write(&client_ibuf.w) < 0)
goto lost_server;
}
@@ -523,33 +488,33 @@ client_write(int fd, const char *data, size_t size)
/* Dispatch imsgs when in wait state (before MSG_READY). */
int
client_dispatch_wait(void *data0)
client_dispatch_wait(void *data)
{
struct imsg imsg;
char *data;
ssize_t n, datalen;
struct msg_stdout_data stdoutdata;
struct msg_stderr_data stderrdata;
int retval;
struct imsg imsg;
ssize_t n, datalen;
struct msg_shell_data shelldata;
struct msg_exit_data exitdata;
struct msg_stdout_data stdoutdata;
struct msg_stderr_data stderrdata;
const char *shellcmd = data;
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
log_debug("got %d from server", imsg.hdr.type);
switch (imsg.hdr.type) {
case MSG_EXIT:
case MSG_SHUTDOWN:
if (datalen != sizeof retval && datalen != 0)
fatalx("bad MSG_EXIT size");
if (datalen == sizeof retval) {
memcpy(&retval, data, sizeof retval);
client_exitval = retval;
if (datalen != sizeof exitdata) {
if (datalen != 0)
fatalx("bad MSG_EXIT size");
} else {
memcpy(&exitdata, imsg.data, sizeof exitdata);
client_exitval = exitdata.retcode;
}
imsg_free(&imsg);
return (-1);
@@ -569,19 +534,17 @@ client_dispatch_wait(void *data0)
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
fatalx("bad MSG_STDOUT size");
memcpy(&stdoutdata, data, sizeof stdoutdata);
fatalx("bad MSG_STDOUT");
memcpy(&stdoutdata, imsg.data, sizeof stdoutdata);
client_write(STDOUT_FILENO, stdoutdata.data,
stdoutdata.size);
client_write(STDOUT_FILENO, stdoutdata.data, stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
fatalx("bad MSG_STDERR size");
memcpy(&stderrdata, data, sizeof stderrdata);
fatalx("bad MSG_STDERR");
memcpy(&stderrdata, imsg.data, sizeof stderrdata);
client_write(STDERR_FILENO, stderrdata.data,
stderrdata.size);
client_write(STDERR_FILENO, stderrdata.data, stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
@@ -595,19 +558,23 @@ client_dispatch_wait(void *data0)
imsg_free(&imsg);
return (-1);
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_SHELL string");
if (datalen != sizeof shelldata)
fatalx("bad MSG_SHELL size");
memcpy(&shelldata, imsg.data, sizeof shelldata);
shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
clear_signals(0);
shell_exec(data, data0);
shell_exec(shelldata.shell, shellcmd);
/* NOTREACHED */
case MSG_DETACH:
case MSG_DETACHKILL:
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
default:
fatalx("unexpected message");
}
imsg_free(&imsg);
@@ -618,28 +585,25 @@ client_dispatch_wait(void *data0)
int
client_dispatch_attached(void)
{
struct imsg imsg;
struct sigaction sigact;
char *data;
ssize_t n, datalen;
struct imsg imsg;
struct msg_lock_data lockdata;
struct sigaction sigact;
ssize_t n, datalen;
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
log_debug("got %d from server", imsg.hdr.type);
switch (imsg.hdr.type) {
case MSG_DETACH:
case MSG_DETACHKILL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_DETACH string");
case MSG_DETACH:
if (datalen != 0)
fatalx("bad MSG_DETACH size");
client_exitsession = xstrdup(data);
client_exittype = imsg.hdr.type;
if (imsg.hdr.type == MSG_DETACHKILL)
client_exitreason = CLIENT_EXIT_DETACHED_HUP;
@@ -648,7 +612,8 @@ client_dispatch_attached(void)
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int))
if (datalen != 0 &&
datalen != sizeof (struct msg_exit_data))
fatalx("bad MSG_EXIT size");
client_write_server(MSG_EXITING, NULL, 0);
@@ -681,12 +646,16 @@ client_dispatch_attached(void)
kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_LOCK string");
if (datalen != sizeof lockdata)
fatalx("bad MSG_LOCK size");
memcpy(&lockdata, imsg.data, sizeof lockdata);
system(data);
lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
system(lockdata.cmd);
client_write_server(MSG_UNLOCK, NULL, 0);
break;
default:
fatalx("unexpected message");
}
imsg_free(&imsg);
+4 -11
View File
@@ -103,20 +103,13 @@ clock_draw(struct screen_write_ctx *ctx, int colour, int style)
struct grid_cell gc;
char tim[64], *ptr;
time_t t;
struct tm *tm;
u_int i, j, x, y, idx;
t = time(NULL);
tm = localtime(&t);
if (style == 0) {
strftime(tim, sizeof tim, "%l:%M ", localtime(&t));
if (tm->tm_hour >= 12)
strlcat(tim, "PM", sizeof tim);
else
strlcat(tim, "AM", sizeof tim);
} else
strftime(tim, sizeof tim, "%H:%M", tm);
if (style == 0)
strftime(tim, sizeof tim, "%l:%M %p", localtime(&t));
else
strftime(tim, sizeof tim, "%H:%M", localtime(&t));
screen_write_clearscreen(ctx);
+16 -91
View File
@@ -18,11 +18,7 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -34,59 +30,34 @@ enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
"c:drt:", 0, 0,
"[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER,
"drt:", 0, 0,
"[-dr] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON,
NULL,
NULL,
cmd_attach_session_exec
};
enum cmd_retval
cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
const char *cflag)
cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
{
struct session *s;
struct client *c;
struct winlink *wl = NULL;
struct window *w = NULL;
struct window_pane *wp = NULL;
const char *update;
char *cause;
u_int i;
int fd;
struct format_tree *ft;
char *cp;
struct session *s;
struct client *c;
const char *update;
char *cause;
u_int i;
if (RB_EMPTY(&sessions)) {
cmdq_error(cmdq, "no sessions");
return (CMD_RETURN_ERROR);
}
if (tflag == NULL) {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
} else if (tflag[strcspn(tflag, ":.")] != '\0') {
if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
} else {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
w = cmd_lookup_windowid(tflag);
if (w == NULL && (wp = cmd_lookup_paneid(tflag)) != NULL)
w = wp->window;
if (w != NULL)
wl = winlink_find_by_window(&s->windows, w);
}
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL);
if (wl != NULL) {
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, wl);
}
if (cmdq->client->session != NULL) {
if (dflag) {
/*
@@ -99,33 +70,10 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
continue;
if (c == cmdq->client)
continue;
server_write_client(c, MSG_DETACH,
c->session->name,
strlen(c->session->name) + 1);
server_write_client(c, MSG_DETACH, NULL, 0);
}
}
if (cflag != NULL) {
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, s->curw);
format_window_pane(ft, s->curw->window->active);
cp = format_expand(ft, cflag);
format_free(ft);
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
close(s->cwd);
s->cwd = fd;
}
cmdq->client->session = s;
notify_attached_session_changed(cmdq->client);
session_update_activity(s);
@@ -138,34 +86,11 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
return (CMD_RETURN_ERROR);
}
if (cflag != NULL) {
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, s->curw);
format_window_pane(ft, s->curw->window->active);
cp = format_expand(ft, cflag);
format_free(ft);
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
close(s->cwd);
s->cwd = fd;
}
if (rflag)
cmdq->client->flags |= CLIENT_READONLY;
if (dflag) {
server_write_session(s, MSG_DETACH, s->name,
strlen(s->name) + 1);
}
if (dflag)
server_write_session(s, MSG_DETACH, NULL, 0);
update = options_get_string(&s->options, "update-environment");
environ_update(update, &cmdq->client->environ, &s->environ);
@@ -191,5 +116,5 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
return (cmd_attach_session(cmdq, args_get(args, 't'),
args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c')));
args_has(args, 'd'), args_has(args, 'r')));
}
+15 -12
View File
@@ -27,6 +27,7 @@
* Bind a key to a command, this recurses through cmd_*.
*/
enum cmd_retval cmd_bind_key_check(struct args *);
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_q *, int);
@@ -37,9 +38,23 @@ const struct cmd_entry cmd_bind_key_entry = {
"[-cnr] [-t key-table] key command [arguments]",
0,
NULL,
cmd_bind_key_check,
cmd_bind_key_exec
};
enum cmd_retval
cmd_bind_key_check(struct args *args)
{
if (args_has(args, 't')) {
if (args->argc != 2 && args->argc != 3)
return (CMD_RETURN_ERROR);
} else {
if (args->argc < 2)
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
enum cmd_retval
cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -48,18 +63,6 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
struct cmd_list *cmdlist;
int key;
if (args_has(args, 't')) {
if (args->argc != 2 && args->argc != 3) {
cmdq_error(cmdq, "not enough arguments");
return (CMD_RETURN_ERROR);
}
} else {
if (args->argc < 2) {
cmdq_error(cmdq, "not enough arguments");
return (CMD_RETURN_ERROR);
}
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
+6
View File
@@ -34,12 +34,17 @@ const struct cmd_entry cmd_break_pane_entry = {
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_break_pane_exec
};
enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "break pane is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct winlink *wl;
struct session *s;
@@ -111,4 +116,5 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
return (CMD_RETURN_NORMAL);
#endif
}
+1
View File
@@ -42,6 +42,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_capture_pane_exec
};
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_choose_buffer_entry = {
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_buffer_exec
};
+1
View File
@@ -37,6 +37,7 @@ const struct cmd_entry cmd_choose_client_entry = {
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_client_exec
};
+1
View File
@@ -39,6 +39,7 @@ const struct cmd_entry cmd_choose_list_entry = {
"[-l items] " CMD_TARGET_WINDOW_USAGE "[template]",
0,
NULL,
NULL,
cmd_choose_list_exec
};
+8 -4
View File
@@ -41,6 +41,7 @@ const struct cmd_entry cmd_choose_tree_entry = {
"[-W format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_choose_tree_exec
};
@@ -50,6 +51,7 @@ const struct cmd_entry cmd_choose_session_entry = {
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_tree_exec
};
@@ -59,6 +61,7 @@ const struct cmd_entry cmd_choose_window_entry = {
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
0,
NULL,
NULL,
cmd_choose_tree_exec
};
@@ -86,7 +89,10 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
if ((s = c->session) == NULL)
return (CMD_RETURN_ERROR);
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
@@ -226,10 +232,8 @@ windows_only:
window_choose_ready(wl->window->active, cur_win, NULL);
if (args_has(args, 'u')) {
if (args_has(args, 'u'))
window_choose_expand_all(wl->window->active);
window_choose_set_current(wl->window->active, cur_win);
}
return (CMD_RETURN_NORMAL);
}
+1
View File
@@ -32,6 +32,7 @@ const struct cmd_entry cmd_clear_history_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_clear_history_exec
};
+1
View File
@@ -32,6 +32,7 @@ const struct cmd_entry cmd_clock_mode_entry = {
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_clock_mode_exec
};
+2
View File
@@ -30,6 +30,7 @@
*/
void cmd_command_prompt_key_binding(struct cmd *, int);
int cmd_command_prompt_check(struct args *);
enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmd_q *);
int cmd_command_prompt_callback(void *, const char *);
@@ -41,6 +42,7 @@ const struct cmd_entry cmd_command_prompt_entry = {
"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
0,
cmd_command_prompt_key_binding,
NULL,
cmd_command_prompt_exec
};
+1
View File
@@ -38,6 +38,7 @@ const struct cmd_entry cmd_confirm_before_entry = {
"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
0,
cmd_confirm_before_key_binding,
NULL,
cmd_confirm_before_exec
};
+4 -5
View File
@@ -33,6 +33,7 @@ const struct cmd_entry cmd_copy_mode_entry = {
"[-u] " CMD_TARGET_PANE_USAGE,
0,
cmd_copy_mode_key_binding,
NULL,
cmd_copy_mode_exec
};
@@ -53,11 +54,9 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
if (wp->mode != &window_copy_mode) {
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
return (CMD_RETURN_NORMAL);
window_copy_init_from_pane(wp);
}
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
return (CMD_RETURN_NORMAL);
window_copy_init_from_pane(wp);
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
window_copy_pageup(wp);
+1
View File
@@ -34,6 +34,7 @@ const struct cmd_entry cmd_delete_buffer_entry = {
CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_delete_buffer_exec
};
+9 -17
View File
@@ -18,8 +18,6 @@
#include <sys/types.h>
#include <string.h>
#include "tmux.h"
/*
@@ -34,6 +32,7 @@ const struct cmd_entry cmd_detach_client_entry = {
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
CMD_READONLY,
NULL,
NULL,
cmd_detach_client_exec
};
@@ -42,8 +41,8 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c, *c2;
struct session *s;
enum msgtype msgtype;
struct session *s;
enum msgtype msgtype;
u_int i;
if (args_has(args, 'P'))
@@ -58,10 +57,8 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
server_write_client(c, msgtype, c->session->name,
strlen(c->session->name) + 1);
if (c != NULL && c->session == s)
server_write_client(c, msgtype, NULL, 0);
}
} else {
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
@@ -71,17 +68,12 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
if (args_has(args, 'a')) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c2 = ARRAY_ITEM(&clients, i);
if (c2 == NULL || c2->session == NULL ||
c2 == c)
if (c2 == NULL || c == c2)
continue;
server_write_client(c2, msgtype,
c2->session->name,
strlen(c2->session->name) + 1);
server_write_client(c2, msgtype, NULL, 0);
}
} else {
server_write_client(c, msgtype, c->session->name,
strlen(c->session->name) + 1);
}
} else
server_write_client(c, msgtype, NULL, 0);
}
return (CMD_RETURN_STOP);
+4 -3
View File
@@ -36,6 +36,7 @@ const struct cmd_entry cmd_display_message_entry = {
" [message]",
0,
NULL,
NULL,
cmd_display_message_exec
};
@@ -70,9 +71,9 @@ cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (args_has(args, 'c')) {
c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
} else {
c = cmd_current_client(cmdq);
if (c == NULL && !args_has(self->args, 'p')) {
+1
View File
@@ -32,6 +32,7 @@ const struct cmd_entry cmd_display_panes_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_display_panes_exec
};
+1
View File
@@ -48,6 +48,7 @@ const struct cmd_entry cmd_find_window_entry = {
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
0,
NULL,
NULL,
cmd_find_window_exec
};
+1
View File
@@ -32,6 +32,7 @@ const struct cmd_entry cmd_has_session_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_has_session_exec
};
+1 -3
View File
@@ -41,6 +41,7 @@ const struct cmd_entry cmd_if_shell_entry = {
"[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0,
NULL,
NULL,
cmd_if_shell_exec
};
@@ -147,9 +148,6 @@ cmd_if_shell_done(struct cmd_q *cmdq1)
struct cmd_if_shell_data *cdata = cmdq1->data;
struct cmd_q *cmdq = cdata->cmdq;
if (cmdq1->client_exit >= 0)
cmdq->client_exit = cmdq1->client_exit;
if (!cmdq_free(cmdq) && !cdata->bflag)
cmdq_continue(cmdq);
+7
View File
@@ -39,6 +39,7 @@ const struct cmd_entry cmd_join_pane_entry = {
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
cmd_join_pane_key_binding,
NULL,
cmd_join_pane_exec
};
@@ -48,6 +49,7 @@ const struct cmd_entry cmd_move_pane_entry = {
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
NULL,
NULL,
cmd_join_pane_exec
};
@@ -74,6 +76,10 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq)
enum cmd_retval
join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
{
#ifdef TMATE
cmdq_error(cmdq, "join pane is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *dst_s;
struct winlink *src_wl, *dst_wl;
@@ -168,4 +174,5 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
notify_window_layout_changed(dst_w);
return (CMD_RETURN_NORMAL);
#endif
}
+1
View File
@@ -34,6 +34,7 @@ const struct cmd_entry cmd_kill_pane_entry = {
"[-a] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_kill_pane_exec
};
+2 -11
View File
@@ -35,23 +35,14 @@ const struct cmd_entry cmd_kill_server_entry = {
"",
0,
NULL,
cmd_kill_server_exec
};
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"", 0, 0,
"",
CMD_STARTSERVER,
NULL,
cmd_kill_server_exec
};
enum cmd_retval
cmd_kill_server_exec(struct cmd *self, unused struct cmd_q *cmdq)
cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq)
{
if (self->entry == &cmd_kill_server_entry)
kill(getpid(), SIGTERM);
kill(getpid(), SIGTERM);
return (CMD_RETURN_NORMAL);
}
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_kill_session_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_kill_session_exec
};
+1
View File
@@ -32,6 +32,7 @@ const struct cmd_entry cmd_kill_window_entry = {
"[-a] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_kill_window_exec
};
+6
View File
@@ -34,12 +34,17 @@ const struct cmd_entry cmd_link_window_entry = {
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_link_window_exec
};
enum cmd_retval
cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "link window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *src, *dst;
struct winlink *wl;
@@ -61,4 +66,5 @@ cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_list_buffers_entry = {
"[-F format]",
0,
NULL,
NULL,
cmd_list_buffers_exec
};
+1
View File
@@ -36,6 +36,7 @@ const struct cmd_entry cmd_list_clients_entry = {
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
NULL,
NULL,
cmd_list_clients_exec
};
+1
View File
@@ -32,6 +32,7 @@ const struct cmd_entry cmd_list_commands_entry = {
"",
0,
NULL,
NULL,
cmd_list_commands_exec
};
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_list_keys_entry = {
"[-t key-table]",
0,
NULL,
NULL,
cmd_list_keys_exec
};
+1
View File
@@ -41,6 +41,7 @@ const struct cmd_entry cmd_list_panes_entry = {
"[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_list_panes_exec
};
+1
View File
@@ -36,6 +36,7 @@ const struct cmd_entry cmd_list_sessions_entry = {
"[-F format]",
0,
NULL,
NULL,
cmd_list_sessions_exec
};
+1
View File
@@ -39,6 +39,7 @@ const struct cmd_entry cmd_list_windows_entry = {
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_list_windows_exec
};
+18 -16
View File
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,6 +39,7 @@ const struct cmd_entry cmd_load_buffer_entry = {
CMD_BUFFER_USAGE " path",
0,
NULL,
NULL,
cmd_load_buffer_exec
};
@@ -50,11 +50,11 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
FILE *f;
const char *path;
const char *path, *newpath, *wd;
char *pdata, *new_pdata, *cause;
size_t psize;
u_int limit;
int ch, error, buffer, *buffer_ptr, cwd, fd;
int ch, error, buffer, *buffer_ptr;
if (!args_has(args, 'b'))
buffer = -1;
@@ -72,7 +72,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
buffer_ptr = xmalloc(sizeof *buffer_ptr);
*buffer_ptr = buffer;
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
error = server_set_stdin_callback (c, cmd_load_buffer_callback,
buffer_ptr, &cause);
if (error != 0) {
cmdq_error(cmdq, "%s: %s", path, cause);
@@ -82,17 +82,20 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_WAIT);
}
if (c != NULL && c->session == NULL)
cwd = c->cwd;
else if ((s = cmd_current_session(cmdq, 0)) != NULL)
cwd = s->cwd;
else
cwd = AT_FDCWD;
if ((fd = openat(cwd, path, O_RDONLY)) == -1 ||
(f = fdopen(fd, "rb")) == NULL) {
if (fd != -1)
close(fd);
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(cmdq, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
if ((f = fopen(path, "rb")) == NULL) {
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
@@ -169,7 +172,6 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
/* No context so can't use server_client_msg_error. */
evbuffer_add_printf(c->stderr_data, "no buffer %d\n", *buffer);
server_push_stderr(c);
free(pdata);
}
free(data);
+3
View File
@@ -36,6 +36,7 @@ const struct cmd_entry cmd_lock_server_entry = {
"",
0,
NULL,
NULL,
cmd_lock_server_exec
};
@@ -45,6 +46,7 @@ const struct cmd_entry cmd_lock_session_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_lock_server_exec
};
@@ -54,6 +56,7 @@ const struct cmd_entry cmd_lock_client_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_lock_server_exec
};
+6
View File
@@ -34,12 +34,17 @@ const struct cmd_entry cmd_move_window_entry = {
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_move_window_exec
};
enum cmd_retval
cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "move window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *src, *dst, *s;
struct winlink *wl;
@@ -72,4 +77,5 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+38 -58
View File
@@ -18,8 +18,6 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
@@ -32,39 +30,46 @@
* Create a new session and attach to the current terminal unless -d is given.
*/
enum cmd_retval cmd_new_session_check(struct args *);
enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
"Ac:dDF:n:Ps:t:x:y:", 0, 1,
"[-AdDP] [-c start-directory] [-F format] [-n window-name] "
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
"[command]",
CMD_STARTSERVER|CMD_CANTNEST,
"AdDF:n:Ps:t:x:y:", 0, 1,
"[-AdDP] [-F format] [-n window-name] [-s session-name] "
CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON,
NULL,
cmd_new_session_check,
cmd_new_session_exec
};
enum cmd_retval
cmd_new_session_check(struct args *args)
{
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n')))
return (CMD_RETURN_ERROR);
return (CMD_RETURN_NORMAL);
}
enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c = cmdq->client, *c0;
struct client *c = cmdq->client;
struct session *s, *groupwith;
struct window *w;
struct environ env;
struct termios tio, *tiop;
const char *newname, *target, *update, *errstr, *template;
struct passwd *pw;
const char *newname, *target, *update, *cwd, *errstr;
const char *template;
char *cmd, *cause, *cp;
int detached, already_attached, idx, cwd, fd = -1;
int detached, idx;
u_int sx, sy;
int already_attached;
struct format_tree *ft;
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
cmdq_error(cmdq, "command or window name given with target");
return (CMD_RETURN_ERROR);
}
newname = args_get(args, 's');
if (newname != NULL) {
if (!session_check_name(newname)) {
@@ -74,7 +79,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (session_find(newname) != NULL) {
if (args_has(args, 'A')) {
return (cmd_attach_session(cmdq, newname,
args_has(args, 'D'), 0, NULL));
args_has(args, 'D'), 0));
}
cmdq_error(cmdq, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR);
@@ -99,34 +104,6 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (c != NULL && c->session != NULL)
already_attached = 1;
/* Get the new session working directory. */
if (args_has(args, 'c')) {
ft = format_create();
if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c0);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (c != NULL && c->session == NULL)
cwd = c->cwd;
else if ((c0 = cmd_current_client(cmdq)) != NULL)
cwd = c0->session->cwd;
else {
fd = open(".", O_RDONLY);
cwd = fd;
}
/*
* Save the termios settings, part of which is used for new windows in
* this session.
@@ -148,10 +125,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (server_client_open(c, NULL, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause);
goto error;
return (CMD_RETURN_ERROR);
}
}
/* Get the new session working directory. */
if (c != NULL && c->cwd != NULL)
cwd = c->cwd;
else {
pw = getpwuid(getuid());
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
cwd = pw->pw_dir;
else
cwd = "/";
}
/* Find new session size. */
if (c != NULL) {
sx = c->tty.sx;
@@ -164,14 +152,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(cmdq, "width %s", errstr);
goto error;
return (CMD_RETURN_ERROR);
}
}
if (detached && args_has(args, 'y')) {
sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(cmdq, "height %s", errstr);
goto error;
return (CMD_RETURN_ERROR);
}
}
if (sy > 0 && options_get_number(&global_s_options, "status"))
@@ -201,7 +189,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (s == NULL) {
cmdq_error(cmdq, "create session failed: %s", cause);
free(cause);
goto error;
return (CMD_RETURN_ERROR);
}
environ_free(&env);
@@ -252,8 +240,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
template = NEW_SESSION_TEMPLATE;
ft = format_create();
if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c0);
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
cp = format_expand(ft, template);
@@ -265,13 +253,5 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (!detached)
cmdq->client_exit = 0;
if (fd != -1)
close(fd);
return (CMD_RETURN_NORMAL);
error:
if (fd != -1)
close(fd);
return (CMD_RETURN_ERROR);
}
+10 -45
View File
@@ -18,11 +18,7 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -39,6 +35,7 @@ const struct cmd_entry cmd_new_window_entry = {
CMD_TARGET_WINDOW_USAGE " [command]",
0,
NULL,
NULL,
cmd_new_window_exec
};
@@ -49,9 +46,9 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct session *s;
struct winlink *wl;
struct client *c;
const char *cmd, *template;
const char *cmd, *cwd, *template;
char *cause, *cp;
int idx, last, detached, cwd, fd = -1;
int idx, last, detached;
struct format_tree *ft;
if (args_has(args, 'a')) {
@@ -82,37 +79,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
}
detached = args_has(args, 'd');
if (args->argc == 0)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
if (args_has(args, 'c')) {
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, s->curw);
format_window_pane(ft, s->curw->window->active);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
cwd = s->cwd;
wl = NULL;
if (idx != -1)
wl = winlink_find_by_index(&s->windows, idx);
@@ -133,13 +99,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
}
}
if (args->argc == 0)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
cwd = cmd_get_default_path(cmdq, args_get(args, 'c'));
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause);
if (wl == NULL) {
cmdq_error(cmdq, "create window failed: %s", cause);
free(cause);
goto error;
return (CMD_RETURN_ERROR);
}
if (!detached) {
session_select(s, wl->idx);
@@ -165,12 +137,5 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
if (fd != -1)
close(fd);
return (CMD_RETURN_NORMAL);
error:
if (fd != -1)
close(fd);
return (CMD_RETURN_ERROR);
}
+1
View File
@@ -38,6 +38,7 @@ const struct cmd_entry cmd_paste_buffer_entry = {
"[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_paste_buffer_exec
};
+1
View File
@@ -41,6 +41,7 @@ const struct cmd_entry cmd_pipe_pane_entry = {
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
NULL,
cmd_pipe_pane_exec
};
+27 -13
View File
@@ -23,6 +23,7 @@
#include <time.h>
#include "tmux.h"
#include "tmate.h"
/* Create new command queue. */
struct cmd_q *
@@ -35,7 +36,7 @@ cmdq_new(struct client *c)
cmdq->dead = 0;
cmdq->client = c;
cmdq->client_exit = -1;
cmdq->client_exit = 0;
TAILQ_INIT(&cmdq->queue);
cmdq->item = NULL;
@@ -69,7 +70,9 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
va_start(ap, fmt);
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
@@ -102,7 +105,9 @@ cmdq_info(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
va_start(ap, fmt);
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
@@ -132,14 +137,21 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
va_end(ap);
if (c == NULL) {
#ifdef TMATE
if (cmd->file && cmd->line)
xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
else
xasprintf(&cause, "%s", msg);
#else
xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
#endif
ARRAY_ADD(&cfg_causes, cause);
} else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
evbuffer_add(c->stderr_data, msg, msglen);
evbuffer_add(c->stderr_data, "\n", 1);
server_push_stderr(c);
c->retval = 1;
c->retcode = 1;
} else {
*msg = toupper((u_char) *msg);
status_message_set(c, "%s", msg);
@@ -150,17 +162,17 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
/* Print a guard line. */
int
cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
cmdq_guard(struct cmd_q *cmdq, const char *guard)
{
struct client *c = cmdq->client;
if (c == NULL)
if (c == NULL || c->session == NULL)
return 0;
if (!(c->flags & CLIENT_CONTROL))
return 0;
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
(long) cmdq->time, cmdq->number, flags);
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u\n", guard,
(long) cmdq->time, cmdq->number);
server_push_stdout(c);
return 1;
}
@@ -195,7 +207,7 @@ cmdq_continue(struct cmd_q *cmdq)
{
struct cmd_q_item *next;
enum cmd_retval retval;
int empty, guard, flags;
int empty, guard;
char s[1024];
notify_disable();
@@ -221,16 +233,18 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->time = time(NULL);
cmdq->number++;
flags = !!(cmdq->cmd->flags & CMD_CONTROL);
guard = cmdq_guard(cmdq, "begin", flags);
#ifdef TMATE
if (tmate_should_replicate_cmd(cmdq->cmd->entry))
tmate_exec_cmd(s);
#endif
guard = cmdq_guard(cmdq, "begin");
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
if (guard) {
if (retval == CMD_RETURN_ERROR)
cmdq_guard(cmdq, "error", flags);
cmdq_guard(cmdq, "error");
else
cmdq_guard(cmdq, "end", flags);
cmdq_guard(cmdq, "end");
}
if (retval == CMD_RETURN_ERROR)
@@ -255,7 +269,7 @@ cmdq_continue(struct cmd_q *cmdq)
} while (cmdq->item != NULL);
empty:
if (cmdq->client_exit > 0)
if (cmdq->client_exit)
cmdq->client->flags |= CLIENT_EXIT;
if (cmdq->emptyfn != NULL)
cmdq->emptyfn(cmdq); /* may free cmdq */
+2 -1
View File
@@ -29,9 +29,10 @@ enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
"C:St:", 0, 0,
"[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
"[-S] [-C size]" CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_refresh_client_exec
};
+1
View File
@@ -34,6 +34,7 @@ const struct cmd_entry cmd_rename_session_entry = {
CMD_TARGET_SESSION_USAGE " new-name",
0,
NULL,
NULL,
cmd_rename_session_exec
};
+1
View File
@@ -34,6 +34,7 @@ const struct cmd_entry cmd_rename_window_entry = {
CMD_TARGET_WINDOW_USAGE " new-name",
0,
NULL,
NULL,
cmd_rename_window_exec
};
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_resize_pane_entry = {
"[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]",
0,
cmd_resize_pane_key_binding,
NULL,
cmd_resize_pane_exec
};
+2 -1
View File
@@ -36,6 +36,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
NULL,
cmd_respawn_pane_exec
};
@@ -77,7 +78,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = args->argv[0];
else
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn pane failed: %s", cause);
free(cause);
environ_free(&env);
+2 -1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_respawn_window_entry = {
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
0,
NULL,
NULL,
cmd_respawn_window_exec
};
@@ -79,7 +80,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = args->argv[0];
else
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn window failed: %s", cause);
free(cause);
environ_free(&env);
+1
View File
@@ -33,6 +33,7 @@ const struct cmd_entry cmd_rotate_window_entry = {
"[-DU] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_rotate_window_key_binding,
NULL,
cmd_rotate_window_exec
};
+1
View File
@@ -41,6 +41,7 @@ const struct cmd_entry cmd_run_shell_entry = {
"[-b] " CMD_TARGET_PANE_USAGE " shell-command",
0,
NULL,
NULL,
cmd_run_shell_exec
};
+31 -25
View File
@@ -20,10 +20,8 @@
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -39,6 +37,7 @@ const struct cmd_entry cmd_save_buffer_entry = {
"[-a] " CMD_BUFFER_USAGE " path",
0,
NULL,
NULL,
cmd_save_buffer_exec
};
@@ -48,6 +47,7 @@ const struct cmd_entry cmd_show_buffer_entry = {
CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_save_buffer_exec
};
@@ -55,14 +55,17 @@ enum cmd_retval
cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c = cmdq->client;
struct client *c;
struct session *s;
struct paste_buffer *pb;
const char *path;
char *cause, *start, *end, *msg;
size_t size, used, msglen;
int cwd, fd, buffer;
const char *path, *newpath, *wd;
char *cause, *start, *end;
size_t size, used;
int buffer;
mode_t mask;
FILE *f;
char *msg;
size_t msglen;
if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) {
@@ -89,6 +92,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
else
path = args->argv[0];
if (strcmp(path, "-") == 0) {
c = cmdq->client;
if (c == NULL) {
cmdq_error(cmdq, "can't write to stdout");
return (CMD_RETURN_ERROR);
@@ -98,26 +102,28 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
goto do_print;
}
if (c != NULL && c->session == NULL)
cwd = c->cwd;
else if ((s = cmd_current_session(cmdq, 0)) != NULL)
cwd = s->cwd;
else
cwd = AT_FDCWD;
f = NULL;
if (args_has(self->args, 'a')) {
fd = openat(cwd, path, O_CREAT|O_RDWR|O_APPEND, 0600);
if (fd != -1)
f = fdopen(fd, "ab");
} else {
fd = openat(cwd, path, O_CREAT|O_RDWR, 0600);
if (fd != -1)
f = fdopen(fd, "wb");
c = cmdq->client;
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(cmdq, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
mask = umask(S_IRWXG | S_IRWXO);
if (args_has(self->args, 'a'))
f = fopen(path, "ab");
else
f = fopen(path, "wb");
umask(mask);
if (f == NULL) {
if (fd != -1)
close(fd);
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
}
+3
View File
@@ -33,6 +33,7 @@ const struct cmd_entry cmd_select_layout_entry = {
"[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
0,
cmd_select_layout_key_binding,
NULL,
cmd_select_layout_exec
};
@@ -42,6 +43,7 @@ const struct cmd_entry cmd_next_layout_entry = {
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_select_layout_exec
};
@@ -51,6 +53,7 @@ const struct cmd_entry cmd_previous_layout_entry = {
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_select_layout_exec
};
+2
View File
@@ -33,6 +33,7 @@ const struct cmd_entry cmd_select_pane_entry = {
"[-lDLRU] " CMD_TARGET_PANE_USAGE,
0,
cmd_select_pane_key_binding,
NULL,
cmd_select_pane_exec
};
@@ -42,6 +43,7 @@ const struct cmd_entry cmd_last_pane_entry = {
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_select_pane_exec
};
+4
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_select_window_entry = {
"[-lnpT] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_window_key_binding,
NULL,
cmd_select_window_exec
};
@@ -44,6 +45,7 @@ const struct cmd_entry cmd_next_window_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_key_binding,
NULL,
cmd_select_window_exec
};
@@ -53,6 +55,7 @@ const struct cmd_entry cmd_previous_window_entry = {
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_key_binding,
NULL,
cmd_select_window_exec
};
@@ -62,6 +65,7 @@ const struct cmd_entry cmd_last_window_entry = {
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_select_window_exec
};
+3 -1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_send_keys_entry = {
"[-lR] " CMD_TARGET_PANE_USAGE " key ...",
0,
NULL,
NULL,
cmd_send_keys_exec
};
@@ -44,6 +45,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
"[-2] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_send_keys_exec
};
@@ -54,7 +56,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
struct window_pane *wp;
struct session *s;
struct input_ctx *ictx;
const u_char *str;
const char *str;
int i, key;
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
+174
View File
@@ -0,0 +1,174 @@
/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 MIND, 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 <sys/types.h>
#include <sys/utsname.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Show various information about server.
*/
enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"", 0, 0,
"",
0,
NULL,
NULL,
cmd_server_info_exec
};
enum cmd_retval
cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq)
{
struct tty_term *term;
struct client *c;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct tty_code *code;
const struct tty_term_code_entry *ent;
struct utsname un;
struct job *job;
struct grid *gd;
struct grid_line *gl;
u_int i, j, k, lines;
size_t size;
char out[80];
char *tim;
time_t t;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq,
"tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
cmdq_print(cmdq, "socket path %s, debug level %d", socket_path,
debug_level);
if (uname(&un) >= 0) {
cmdq_print(cmdq, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine);
}
if (cfg_file != NULL)
cmdq_print(cmdq, "configuration file is %s", cfg_file);
else
cmdq_print(cmdq, "configuration file not specified");
cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION);
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
cmdq_print(cmdq,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho "
"class=%u] [flags=0x%x/0x%x, references=%u]", i,
c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name,
c->tty.sx, c->tty.sy, c->tty.termname,
c->tty.tio.c_cc[VERASE], c->tty.class,
c->flags, c->tty.flags, c->references);
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Sessions: [%zu]", sizeof (struct grid_cell));
RB_FOREACH(s, sessions, &sessions) {
t = s->creation_time.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x]", s->id, s->name,
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags);
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
cmdq_print(cmdq, "%4u: %s [%ux%u] [flags=0x%x, "
"references=%u, last layout=%d]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references,
w->lastlayout);
j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
lines = size = 0;
gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) {
gl = &gd->linedata[k];
if (gl->celldata == NULL)
continue;
lines++;
size += gl->cellsize *
sizeof *gl->celldata;
}
cmdq_print(cmdq,
"%6u: %s %lu %d %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size);
j++;
}
}
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Terminals:");
LIST_FOREACH(term, &tty_terms, entry) {
cmdq_print(cmdq, "%s [references=%u, flags=0x%x]:",
term->name, term->references, term->flags);
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
code = &term->codes[ent->code];
switch (code->type) {
case TTYCODE_NONE:
cmdq_print(cmdq, "%2u: %s: [missing]",
ent->code, ent->name);
break;
case TTYCODE_STRING:
strnvis(out, code->value.string, sizeof out,
VIS_OCTAL|VIS_TAB|VIS_NL);
cmdq_print(cmdq, "%2u: %s: (string) %s",
ent->code, ent->name, out);
break;
case TTYCODE_NUMBER:
cmdq_print(cmdq, "%2u: %s: (number) %d",
ent->code, ent->name, code->value.number);
break;
case TTYCODE_FLAG:
cmdq_print(cmdq, "%2u: %s: (flag) %s",
ent->code, ent->name,
code->value.flag ? "true" : "false");
break;
}
}
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Jobs:");
LIST_FOREACH(job, &all_jobs, lentry) {
cmdq_print(cmdq, "%s [fd=%d, pid=%d, status=%d]",
job->cmd, job->fd, job->pid, job->status);
}
return (CMD_RETURN_NORMAL);
}
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_set_buffer_entry = {
CMD_BUFFER_USAGE " data",
0,
NULL,
NULL,
cmd_set_buffer_exec
};
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_set_environment_entry = {
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
0,
NULL,
NULL,
cmd_set_environment_exec
};
+5 -43
View File
@@ -60,9 +60,6 @@ struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_q *,
struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_style(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *,
const char *);
const struct cmd_entry cmd_set_option_entry = {
"set-option", "set",
@@ -70,6 +67,7 @@ const struct cmd_entry cmd_set_option_entry = {
"[-agosquw] [-t target-session|target-window] option [value]",
0,
NULL,
NULL,
cmd_set_option_exec
};
@@ -79,6 +77,7 @@ const struct cmd_entry cmd_set_window_option_entry = {
"[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
0,
NULL,
NULL,
cmd_set_option_exec
};
@@ -129,13 +128,8 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
oo = &global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) {
cmdq_error(cmdq,
"couldn't set '%s'%s", optstr,
(!args_has(args, 't') && !args_has(args,
'g')) ? " need target window or -g" : "");
if (wl == NULL)
return (CMD_RETURN_ERROR);
}
oo = &wl->window->options;
}
} else if (table == session_options_table) {
@@ -143,13 +137,8 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
oo = &global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) {
cmdq_error(cmdq,
"couldn't set '%s'%s", optstr,
(!args_has(args, 't') && !args_has(args,
'g')) ? " need target session or -g" : "");
if (s == NULL)
return (CMD_RETURN_ERROR);
}
oo = &s->options;
}
} else {
@@ -172,7 +161,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
}
/* Start or stop timers when automatic-rename changed. */
if (strcmp(oe->name, "automatic-rename") == 0) {
if (strcmp (oe->name, "automatic-rename") == 0) {
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
if ((w = ARRAY_ITEM(&windows, i)) == NULL)
continue;
@@ -307,13 +296,9 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
break;
case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, cmdq, oe, oo, value);
if (o != NULL)
style_update_new(oo, o->name, oe->style);
break;
case OPTIONS_TABLE_ATTRIBUTES:
o = cmd_set_option_attributes(self, cmdq, oe, oo, value);
if (o != NULL)
style_update_new(oo, o->name, oe->style);
break;
case OPTIONS_TABLE_FLAG:
o = cmd_set_option_flag(self, cmdq, oe, oo, value);
@@ -321,9 +306,6 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
case OPTIONS_TABLE_CHOICE:
o = cmd_set_option_choice(self, cmdq, oe, oo, value);
break;
case OPTIONS_TABLE_STYLE:
o = cmd_set_option_style(self, cmdq, oe, oo, value);
break;
}
if (o == NULL)
return (-1);
@@ -472,23 +454,3 @@ cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq,
return (options_set_number(oo, oe->name, choice));
}
/* Set a style option. */
struct options_entry *
cmd_set_option_style(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
struct args *args = self->args;
struct options_entry *o;
int append;
append = args_has(args, 'a');
if ((o = options_set_style(oo, oe->name, value, append)) == NULL) {
cmdq_error(cmdq, "bad style: %s", value);
return (NULL);
}
style_update_old(oo, oe->name, &o->style);
return (o);
}
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_show_environment_entry = {
"[-g] " CMD_TARGET_SESSION_USAGE " [name]",
0,
NULL,
NULL,
cmd_show_environment_exec
};
+3 -109
View File
@@ -20,7 +20,6 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
@@ -32,98 +31,14 @@ enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs",
"IJTt:", 0, 0,
"[-IJT] " CMD_TARGET_CLIENT_USAGE,
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_show_messages_exec
};
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"", 0, 0,
"",
0,
NULL,
cmd_show_messages_exec
};
void cmd_show_messages_server(struct cmd_q *);
void cmd_show_messages_terminals(struct cmd_q *);
void cmd_show_messages_jobs(struct cmd_q *);
void
cmd_show_messages_server(struct cmd_q *cmdq)
{
char *tim;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq, "started %s", tim);
cmdq_print(cmdq, "socket path %s", socket_path);
cmdq_print(cmdq, "debug level %d", debug_level);
cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION);
}
void
cmd_show_messages_terminals(struct cmd_q *cmdq)
{
struct tty_term *term;
const struct tty_term_code_entry *ent;
struct tty_code *code;
u_int i, n;
char out[80];
n = 0;
LIST_FOREACH(term, &tty_terms, entry) {
cmdq_print(cmdq,
"Terminal %u: %s [references=%u, flags=0x%x]:",
n, term->name, term->references, term->flags);
n++;
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
code = &term->codes[ent->code];
switch (code->type) {
case TTYCODE_NONE:
cmdq_print(cmdq, "%4u: %s: [missing]",
ent->code, ent->name);
break;
case TTYCODE_STRING:
strnvis(out, code->value.string, sizeof out,
VIS_OCTAL|VIS_TAB|VIS_NL);
cmdq_print(cmdq, "%4u: %s: (string) %s",
ent->code, ent->name, out);
break;
case TTYCODE_NUMBER:
cmdq_print(cmdq, "%4u: %s: (number) %d",
ent->code, ent->name, code->value.number);
break;
case TTYCODE_FLAG:
cmdq_print(cmdq, "%4u: %s: (flag) %s",
ent->code, ent->name,
code->value.flag ? "true" : "false");
break;
}
}
}
}
void
cmd_show_messages_jobs(struct cmd_q *cmdq)
{
struct job *job;
u_int n;
n = 0;
LIST_FOREACH(job, &all_jobs, lentry) {
cmdq_print(cmdq,
"Job %u: %s [fd=%d, pid=%d, status=%d]",
n, job->cmd, job->fd, job->pid, job->status);
n++;
}
}
enum cmd_retval
cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -132,27 +47,6 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
struct message_entry *msg;
char *tim;
u_int i;
int done;
done = 0;
if (args_has(args, 'I') || self->entry == &cmd_server_info_entry) {
cmd_show_messages_server(cmdq);
done = 1;
}
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
if (done)
cmdq_print(cmdq, "%s", "");
cmd_show_messages_terminals(cmdq);
done = 1;
}
if (args_has(args, 'J') || self->entry == &cmd_server_info_entry) {
if (done)
cmdq_print(cmdq, "%s", "");
cmd_show_messages_jobs(cmdq);
done = 1;
}
if (done)
return (CMD_RETURN_NORMAL);
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
+2
View File
@@ -40,6 +40,7 @@ const struct cmd_entry cmd_show_options_entry = {
"[-gqsvw] [-t target-session|target-window] [option]",
0,
NULL,
NULL,
cmd_show_options_exec
};
@@ -49,6 +50,7 @@ const struct cmd_entry cmd_show_window_options_entry = {
"[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
0,
NULL,
NULL,
cmd_show_options_exec
};
+1 -4
View File
@@ -37,6 +37,7 @@ const struct cmd_entry cmd_source_file_entry = {
"path",
0,
NULL,
NULL,
cmd_source_file_exec
};
@@ -48,7 +49,6 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
char *cause;
cmdq1 = cmdq_new(NULL);
cmdq1->client = cmdq->client;
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;
@@ -95,9 +95,6 @@ cmd_source_file_done(struct cmd_q *cmdq1)
{
struct cmd_q *cmdq = cmdq1->data;
if (cmdq1->client_exit >= 0)
cmdq->client_exit = cmdq1->client_exit;
cmdq_free(cmdq1);
cfg_references--;
+7 -37
View File
@@ -18,10 +18,7 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -40,6 +37,7 @@ const struct cmd_entry cmd_split_window_entry = {
CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_split_window_key_binding,
NULL,
cmd_split_window_exec
};
@@ -60,14 +58,16 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
const char *cmd, *shell, *template;
char *cause, *new_cause, *cp;
const char *cmd, *cwd, *shell;
char *cause, *new_cause;
u_int hlimit;
int size, percentage, cwd, fd = -1;
int size, percentage;
enum layout_type type;
struct layout_cell *lc;
const char *template;
struct client *c;
struct format_tree *ft;
char *cp;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
@@ -83,32 +83,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
if (args_has(args, 'c')) {
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, s->curw);
format_window_pane(ft, s->curw->window->active);
cp = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
cwd = s->cwd;
cwd = cmd_get_default_path(cmdq, args_get(args, 'c'));
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
@@ -181,9 +156,6 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
notify_window_layout_changed(w);
if (fd != -1)
close(fd);
return (CMD_RETURN_NORMAL);
error:
@@ -192,7 +164,5 @@ error:
window_remove_pane(w, new_wp);
cmdq_error(cmdq, "create pane failed: %s", cause);
free(cause);
if (fd != -1)
close(fd);
return (CMD_RETURN_ERROR);
}
+21 -10
View File
@@ -1,8 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2013 Dagobert Michelsen
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,16 +16,28 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include <sys/types.h>
#include "tmux.h"
void
cfmakeraw(struct termios *tio)
/*
* Start the server and do nothing else.
*/
enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"", 0, 0,
"",
CMD_STARTSERVER,
NULL,
NULL,
cmd_start_server_exec
};
enum cmd_retval
cmd_start_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq)
{
tio->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
tio->c_oflag &= ~OPOST;
tio->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
tio->c_cflag &= ~(CSIZE|PARENB);
tio->c_cflag |= CS8;
return (CMD_RETURN_NORMAL);
}
+7 -22
View File
@@ -318,13 +318,10 @@ cmd_string_expand_tilde(const char *s, size_t *p)
{
struct passwd *pw;
struct environ_entry *envent;
char *home, *path, *user, *cp;
int last;
char *home, *path, *username;
home = NULL;
last = cmd_string_getc(s, p);
if (last == EOF || last == '/' || last == ' '|| last == '\t') {
if (cmd_string_getc(s, p) == '/') {
envent = environ_find(&global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
home = envent->value;
@@ -332,27 +329,15 @@ cmd_string_expand_tilde(const char *s, size_t *p)
home = pw->pw_dir;
} else {
cmd_string_ungetc(p);
cp = user = xmalloc(strlen(s));
for (;;) {
last = cmd_string_getc(s, p);
if (last == EOF || last == '/' || last == ' '|| last == '\t')
break;
*cp++ = last;
}
*cp = '\0';
if ((pw = getpwnam(user)) != NULL)
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
return (NULL);
if ((pw = getpwnam(username)) != NULL)
home = pw->pw_dir;
free(user);
free(username);
}
if (home == NULL)
return (NULL);
if (last != EOF)
xasprintf(&path, "%s%c", home, last);
else
xasprintf(&path, "%s", home);
xasprintf(&path, "%s/", home);
return (path);
}
+1
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_suspend_client_entry = {
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_suspend_client_exec
};
+10 -6
View File
@@ -35,6 +35,7 @@ const struct cmd_entry cmd_swap_pane_entry = {
"[-dDU] " CMD_SRCDST_PANE_USAGE,
0,
cmd_swap_pane_key_binding,
NULL,
cmd_swap_pane_exec
};
@@ -74,12 +75,8 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else {
src_wl = cmd_find_pane(cmdq, NULL, NULL, &src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
src_w = src_wl->window;
}
} else
return (CMD_RETURN_NORMAL);
} else {
src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
@@ -88,6 +85,13 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
}
server_unzoom_window(src_w);
#ifdef TMATE
if (src_w != dst_w) {
cmdq_error(cmdq, "swap pane on different window is not supported with tmate");
return (CMD_RETURN_ERROR);
}
#endif
if (src_wp == dst_wp)
return (CMD_RETURN_NORMAL);
+6
View File
@@ -34,12 +34,17 @@ const struct cmd_entry cmd_swap_window_entry = {
"[-d] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_swap_window_exec
};
enum cmd_retval
cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "swap window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
const char *target_src, *target_dst;
struct session *src, *dst;
@@ -83,4 +88,5 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+9 -35
View File
@@ -36,6 +36,7 @@ const struct cmd_entry cmd_switch_client_entry = {
"[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
cmd_switch_client_key_binding,
NULL,
cmd_switch_client_exec
};
@@ -59,13 +60,9 @@ cmd_switch_client_key_binding(struct cmd *self, int key)
enum cmd_retval
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
struct window *w = NULL;
struct window_pane *wp = NULL;
const char *tflag;
struct args *args = self->args;
struct client *c;
struct session *s;
if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR);
@@ -80,7 +77,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
}
}
tflag = args_get(args, 't');
s = NULL;
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
cmdq_error(cmdq, "can't find next session");
@@ -98,33 +95,10 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "can't find last session");
return (CMD_RETURN_ERROR);
}
} else {
if (tflag == NULL) {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
} else if (tflag[strcspn(tflag, ":.")] != '\0') {
if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
} else {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
w = cmd_lookup_windowid(tflag);
if (w == NULL &&
(wp = cmd_lookup_paneid(tflag)) != NULL)
w = wp->window;
if (w != NULL)
wl = winlink_find_by_window(&s->windows, w);
}
if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL);
if (wl != NULL) {
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, wl);
}
}
} else
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
if (c->session != NULL)
c->last_session = c->session;
+13 -10
View File
@@ -26,6 +26,7 @@
* Unbind key from command.
*/
enum cmd_retval cmd_unbind_key_check(struct args *);
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_q *, int);
@@ -35,9 +36,20 @@ const struct cmd_entry cmd_unbind_key_entry = {
"[-acn] [-t key-table] key",
0,
NULL,
cmd_unbind_key_check,
cmd_unbind_key_exec
};
enum cmd_retval
cmd_unbind_key_check(struct args *args)
{
if (args_has(args, 'a') && args->argc != 0)
return (CMD_RETURN_ERROR);
if (!args_has(args, 'a') && args->argc != 1)
return (CMD_RETURN_ERROR);
return (CMD_RETURN_NORMAL);
}
enum cmd_retval
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
@@ -46,22 +58,13 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
int key;
if (!args_has(args, 'a')) {
if (args->argc != 1) {
cmdq_error(cmdq, "missing key");
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
} else {
if (args->argc != 0) {
cmdq_error(cmdq, "key given with -a");
return (CMD_RETURN_ERROR);
}
} else
key = KEYC_NONE;
}
if (args_has(args, 't'))
return (cmd_unbind_key_table(self, cmdq, key));
+6
View File
@@ -32,12 +32,17 @@ const struct cmd_entry cmd_unlink_window_entry = {
"[-k] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_unlink_window_exec
};
enum cmd_retval
cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "unlink window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct winlink *wl;
struct window *w;
@@ -66,4 +71,5 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}
+2 -1
View File
@@ -33,9 +33,10 @@ enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_wait_for_entry = {
"wait-for", "wait",
"LSU", 1, 1,
"[-L|-S|-U] channel",
"[-LSU] channel",
0,
NULL,
NULL,
cmd_wait_for_exec
};
+98 -2
View File
@@ -125,7 +125,9 @@ struct session *cmd_lookup_session(const char *, int *);
struct session *cmd_lookup_session_id(const char *);
struct winlink *cmd_lookup_window(struct session *, const char *, int *);
int cmd_lookup_index(struct session *, const char *, int *);
struct window_pane *cmd_lookup_paneid(const char *);
struct winlink *cmd_lookup_winlink_windowid(struct session *, const char *);
struct window *cmd_lookup_windowid(const char *);
struct session *cmd_window_session(struct cmd_q *, struct window *,
struct winlink **);
struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
@@ -252,6 +254,8 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
goto usage;
if (entry->args_upper != -1 && args->argc > entry->args_upper)
goto usage;
if (entry->check != NULL && entry->check(args) != 0)
goto usage;
cmd = xcalloc(1, sizeof *cmd);
cmd->entry = entry;
@@ -290,8 +294,8 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
size_t off, used;
off = xsnprintf(buf, len, "%s ", cmd->entry->name);
if (off + 1 < len) {
used = args_print(cmd->args, buf + off, len - off - 1);
if (off < len) {
used = args_print(cmd->args, buf + off, len - off);
if (used == 0)
off--;
else
@@ -311,6 +315,7 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
struct session *
cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
{
struct msg_command_data *data = cmdq->msgdata;
struct client *c = cmdq->client;
struct session *s;
struct sessionslist ss;
@@ -352,6 +357,13 @@ cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
return (s);
}
/* Use the session from the TMUX environment variable. */
if (data != NULL && data->pid == getpid() && data->session_id != -1) {
s = session_find_by_id(data->session_id);
if (s != NULL)
return (s);
}
return (cmd_choose_session(prefer_unattached));
}
@@ -1266,3 +1278,87 @@ cmd_template_replace(const char *template, const char *s, int idx)
return (buf);
}
/*
* Return the default path for a new pane, using the given path or the
* default-path option if it is NULL. Several special values are accepted: the
* empty string or relative path for the current pane's working directory, ~
* for the user's home, - for the session working directory, . for the tmux
* server's working directory. The default on failure is the session's working
* directory.
*/
const char *
cmd_get_default_path(struct cmd_q *cmdq, const char *cwd)
{
struct client *c = cmdq->client;
struct session *s;
struct environ_entry *envent;
const char *root;
char tmp[MAXPATHLEN];
struct passwd *pw;
int n;
size_t skip;
static char path[MAXPATHLEN];
if ((s = cmd_current_session(cmdq, 0)) == NULL)
return (NULL);
if (cwd == NULL)
cwd = options_get_string(&s->options, "default-path");
skip = 1;
if (strcmp(cwd, "$HOME") == 0 || strncmp(cwd, "$HOME/", 6) == 0) {
/* User's home directory - $HOME. */
skip = 5;
goto find_home;
} else if (cwd[0] == '~' && (cwd[1] == '\0' || cwd[1] == '/')) {
/* User's home directory - ~. */
goto find_home;
} else if (cwd[0] == '-' && (cwd[1] == '\0' || cwd[1] == '/')) {
/* Session working directory. */
root = s->cwd;
goto complete_path;
} else if (cwd[0] == '.' && (cwd[1] == '\0' || cwd[1] == '/')) {
/* Server working directory. */
if (getcwd(tmp, sizeof tmp) != NULL) {
root = tmp;
goto complete_path;
}
return (s->cwd);
} else if (*cwd == '/') {
/* Absolute path. */
return (cwd);
} else {
/* Empty or relative path. */
if (c != NULL && c->session == NULL && c->cwd != NULL)
root = c->cwd;
else if (s->curw != NULL)
root = osdep_get_cwd(s->curw->window->active->fd);
else
return (s->cwd);
skip = 0;
if (root != NULL)
goto complete_path;
}
return (s->cwd);
find_home:
envent = environ_find(&global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
root = envent->value;
else if ((pw = getpwuid(getuid())) != NULL)
root = pw->pw_dir;
else
return (s->cwd);
complete_path:
if (root[skip] == '\0') {
strlcpy(path, root, sizeof path);
return (path);
}
n = snprintf(path, sizeof path, "%s/%s", root, cwd + skip);
if (n > 0 && (size_t)n < sizeof path)
return (path);
return (s->cwd);
}
+26
View File
@@ -287,3 +287,29 @@ colour_256to16(u_char c)
return (table[c]);
}
/* Convert 256 colour palette to 88. */
u_char
colour_256to88(u_char c)
{
static const u_char table[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 17, 18, 18, 19, 20, 21, 21, 22, 22, 23, 20, 21, 21, 22,
22, 23, 24, 25, 25, 26, 26, 27, 24, 25, 25, 26, 26, 27, 28, 29,
29, 30, 30, 31, 32, 33, 33, 34, 34, 35, 36, 37, 37, 38, 38, 39,
36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43, 40, 41, 41, 42,
42, 43, 44, 45, 45, 46, 46, 47, 32, 33, 33, 34, 34, 35, 36, 37,
37, 38, 38, 39, 36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43,
40, 41, 41, 42, 42, 43, 44, 45, 45, 46, 46, 47, 48, 49, 49, 50,
50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54, 54, 55, 56, 57,
57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63,
48, 49, 49, 50, 50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54,
54, 55, 56, 57, 57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61,
61, 62, 62, 63, 64, 65, 65, 66, 66, 67, 68, 69, 69, 70, 70, 71,
68, 69, 69, 70, 70, 71, 72, 73, 73, 74, 74, 75, 72, 73, 73, 74,
74, 75, 76, 77, 77, 78, 78, 79, 0, 0, 80, 80, 80, 81, 81, 81,
82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87
};
return (table[c]);
}
-32
View File
@@ -30,10 +30,6 @@
#define __packed __attribute__ ((__packed__))
#endif
#ifndef ECHOPRT
#define ECHOPRT 0
#endif
#ifndef HAVE_BSD_TYPES
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
@@ -125,10 +121,6 @@ typedef uint64_t u_int64_t;
#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
#endif
#ifndef O_DIRECTORY
#define O_DIRECTORY 0
#endif
#ifndef INFTIM
#define INFTIM -1
#endif
@@ -160,18 +152,6 @@ typedef uint64_t u_int64_t;
} while (0)
#endif
#ifndef timersub
#define timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while (0)
#endif
#ifndef TTY_NAME_MAX
#define TTY_NAME_MAX 32
#endif
@@ -218,7 +198,6 @@ int daemon(int, int);
#ifndef HAVE_B64_NTOP
/* b64_ntop.c */
#undef b64_ntop /* for Cygwin */
int b64_ntop(const char *, size_t, char *, size_t);
#endif
@@ -245,17 +224,6 @@ int setenv(const char *, const char *, int);
int unsetenv(const char *);
#endif
#ifndef HAVE_CFMAKERAW
/* cfmakeraw.c */
void cfmakeraw(struct termios *);
#endif
#ifndef HAVE_OPENAT
/* openat.c */
#define AT_FDCWD -100
int openat(int, const char *, int, ...);
#endif
#ifdef HAVE_GETOPT
#include <getopt.h>
#else
-1
View File
@@ -21,7 +21,6 @@
#include <fcntl.h>
#include <stdlib.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>
-1
View File
@@ -24,7 +24,6 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "tmux.h"
-1
View File
@@ -24,7 +24,6 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "tmux.h"
-63
View File
@@ -1,63 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 MIND, 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 <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>
#include "tmux.h"
int
openat(int fd, const char *path, int flags, ...)
{
mode_t mode;
va_list ap;
int dotfd, retval, saved_errno;
if (flags & O_CREAT) {
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
} else
mode = 0;
dotfd = -1;
if (fd != AT_FDCWD) {
dotfd = open(".", O_RDONLY);
if (dotfd == -1)
return (-1);
if (fchdir(fd) != 0)
return (-1);
}
retval = open(path, flags, mode);
if (dotfd != -1) {
if (fchdir(dotfd) != 0) {
saved_errno = errno;
close(retval);
close(dotfd);
errno = saved_errno;
return (-1);
}
close(dotfd);
}
return (retval);
}
+17 -37
View File
@@ -1,10 +1,10 @@
# $Id$
# Miscellaneous autofoo bullshit.
AC_INIT(tmux, 1.9)
AC_INIT(tmate, 1.8.4)
AC_CONFIG_AUX_DIR(etc)
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_INIT_AUTOMAKE([foreign])
AC_CANONICAL_HOST
@@ -16,12 +16,8 @@ AC_CANONICAL_HOST
# Set up the compiler in two different ways and say yes we may want to install.
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_MKDIR_P
AC_PROG_INSTALL
# Default tmux.conf goes in /etc not ${prefix}/etc.
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
# Check for various headers. Alternatives included from compat.h.
AC_CHECK_HEADERS(
[ \
@@ -44,6 +40,13 @@ AC_CHECK_HEADERS(
]
)
AC_ARG_ENABLE(
devenv,
AC_HELP_STRING(--enable-devenv, "dev env (localhost, port 2200, no auth checks)"),
found_devenv=$enable_devenv
)
AM_CONDITIONAL(IS_DEVENV, test "x$found_devenv" = xyes)
# Is this a debug build?
#found_debug=yes
AC_ARG_ENABLE(
@@ -111,6 +114,13 @@ AC_MSG_RESULT($found_glibc)
# Look for clock_gettime. Must come before event_init.
AC_SEARCH_LIBS(clock_gettime, rt)
AC_CHECK_LIB(z, inflate, [],
[AC_MSG_ERROR([zlib library required])])
AC_CHECK_LIB(crypto,CRYPTO_new_ex_data, [],
[AC_MSG_ERROR([OpenSSL library required])])
AC_CHECK_LIB(ssl, SSL_library_init, [],
[AC_MSG_ERROR([OpenSSL library required])])
# Look for libevent.
PKG_CHECK_MODULES(
LIBEVENT,
@@ -136,7 +146,7 @@ fi
# Look for curses.
AC_SEARCH_LIBS(
setupterm,
[terminfo curses ncurses tinfo],
[terminfo curses ncurses],
found_curses=yes,
found_curses=no
)
@@ -312,35 +322,11 @@ AM_CONDITIONAL(NO_STRTONUM, [test "x$found_strtonum" = xno])
# Look for strnvis, compat/{vis,unvis}.c used if missing.
AC_CHECK_FUNC(strnvis, found_strnvis=yes, found_strnvis=no)
if test "x$found_strnvis" = xyes; then
AC_MSG_CHECKING(if strnvis is broken)
AC_EGREP_HEADER([strnvis\(char \*, const char \*, size_t, int\)],
vis.h,
AC_MSG_RESULT(no),
[found_strnvis=no])
if test "x$found_strnvis" = xno; then
AC_MSG_RESULT(yes)
fi
fi
if test "x$found_strnvis" = xyes; then
AC_DEFINE(HAVE_VIS)
fi
AM_CONDITIONAL(NO_VIS, [test "x$found_strnvis" = xno])
# Look for cfmakeraw, compat/cfmakeraw.c used if missing.
AC_CHECK_FUNC(cfmakeraw, found_cfmakeraw=yes, found_cfmakeraw=no)
if test "x$found_cfmakeraw" = xyes; then
AC_DEFINE(HAVE_CFMAKERAW)
fi
AM_CONDITIONAL(NO_CFMAKERAW, [test "x$found_cfmakeraw" = xno])
# Look for openat, compat/openat.c used if missing.
AC_CHECK_FUNC(openat, found_openat=yes, found_openat=no)
if test "x$found_openat" = xyes; then
AC_DEFINE(HAVE_OPENAT)
fi
AM_CONDITIONAL(NO_OPENAT, [test "x$found_openat" = xno])
# Look for getopt. glibc's getopt does not enforce argument order and the ways
# of making it do so are stupid, so just use our own instead.
AC_CHECK_FUNC(getopt, found_getopt=yes, found_getopt=no)
@@ -373,7 +359,6 @@ AC_CHECK_FUNCS(
dirfd \
setproctitle \
sysconf \
cfmakeraw \
]
)
@@ -445,10 +430,6 @@ else
AC_MSG_RESULT(no)
fi
# Man page defaults to mdoc.
MANFORMAT=mdoc
AC_SUBST(MANFORMAT)
# Figure out the platform for osdep-*.c and forkpty-*.c.
AC_MSG_CHECKING(platform)
case "$host_os" in
@@ -488,7 +469,6 @@ case "$host_os" in
*solaris*)
AC_MSG_RESULT(sunos)
PLATFORM=sunos
MANFORMAT=man
;;
*hpux*)
AC_MSG_RESULT(hpux)
+2 -5
View File
@@ -55,7 +55,6 @@ control_callback(struct client *c, int closed, unused void *data)
{
char *line, *cause;
struct cmd_list *cmdlist;
struct cmd *cmd;
if (closed)
c->flags |= CLIENT_EXIT;
@@ -73,14 +72,12 @@ control_callback(struct client *c, int closed, unused void *data)
c->cmdq->time = time(NULL);
c->cmdq->number++;
cmdq_guard(c->cmdq, "begin", 1);
cmdq_guard(c->cmdq, "begin");
control_write(c, "parse error: %s", cause);
cmdq_guard(c->cmdq, "error", 1);
cmdq_guard(c->cmdq, "error");
free(cause);
} else {
TAILQ_FOREACH(cmd, &cmdlist->list, qentry)
cmd->flags |= CMD_CONTROL;
cmdq_run(c->cmdq, cmdlist);
cmd_list_free(cmdlist);
}
+56 -44
View File
@@ -31,59 +31,71 @@ syn keyword tmuxAction any current none
syn keyword tmuxBoolean off on
syn keyword tmuxCmds
\ attach[-session] bind[-key] break-pane breakp capture-pane capturep
\ choose-buffer choose-client choose-list choose-session choose-tree
\ choose-window clear-history clearhist clock-mode command-prompt
\ confirm[-before] copy-mode delete-buffer deleteb detach[-client]
\ display[-message] display-panes displayp find-window findw
\ has[-session] if[-shell] join-pane joinp kill-pane killp kill-server
\ kill-session kill-window killw last-pane lastp last[-window]
\ link-window linkw list-buffers lsb list-clients lsc
\ list-commands lscm list-keys lsk list-panes lsp list-sessions ls
\ list-windows lsw load-buffer loadb lock-client lockc lock[-server]
\ lock-session locks move-pane movep move-window movew new[-session]
\ next-layout nextl next[-window] paste-buffer pasteb pipe-pane pipep
\ previous-layout prevl prev[ious-window] refresh[-client]
\ rename[-session] rename-window renamew resize-pane resizep
\ respawn-pane respawnp respawn-window respawnw rotate-window rotatew
\ run[-shell] save-buffer saveb select-layout selectl
\ select-pane selectp select-window selectw send[-keys] send-prefix
\ server-info info set-buffer setb set-environment setenv set[-option]
\ set-window-option setw show-buffer showb show-environment showenv
\ show-messages showmsgs show[-options] show-window-options showw
\ source[-file] split-window splitw start[-server]
\ suspend-client suspendc swap-pane swapp swap-window swapw
\ switch-client switchc unbind[-key] unlink-window unlinkw wait[-for]
\ attach[-session] detach[-client] has[-session] kill-server
\ kill-session lsc list-clients lscm list-commands ls list-sessions
\ lockc lock-client locks lock-session new[-session] refresh[-client]
\ rename[-session] showmsgs show-messages source[-file] start[-server]
\ suspendc suspend-client switchc switch-client
\ copy-mode
\ breakp break-pane capturep capture-pane choose-client choose-session
\ choose-tree choose-window displayp display-panes findw find-window
\ joinp join-pane killp kill-pane killw kill-window lastp last-pane
\ last[-window] linkw link-window lsp list-panes lsw list-windows movep
\ move-pane movew move-window neww new-window nextl next-layout
\ next[-window] pipep pipe-pane prevl previous-layout prev[ious-window]
\ renamew rename-window resizep resize-pane respawnp respawn-pane
\ respawnw respawn-window rotatew rotate-window selectl select-layout
\ selectp select-pane selectw select-window splitw split-window swapp
\ swap-pane swapw swap-window unlinkw unlink-window
\ bind[-key] lsk list-keys send[-keys] send-prefix unbind[-key]
\ set[-option] setw set-window-option show[-options] showw
\ show-window-options
\ setenv set-environment showenv show-environment
\ command-prompt confirm[-before] display[-message]
\ choose-buffer clearhist clear-history deleteb delete-buffer lsb
\ list-buffers loadb load-buffer pasteb paste-buffer saveb save-buffer
\ setb set-buffer showb show-buffer
\ clock-mode if[-shell] lock[-server] run[-shell] server-info info
\ choose-list
syn keyword tmuxOptsSet
\ buffer-limit escape-time exit-unattached exit-unattached focus-events
\ quiet set-clipboard
\ assume-paste-time base-index bell-action bell-on-alert default-command
\ buffer-limit escape-time exit-unattached exit-unattached quiet
\ set-clipboard
\ base-index bell-action bell-on-alert default-command default-path
\ default-shell default-terminal destroy-unattached detach-on-destroy
\ display-panes-active-colour display-panes-colour display-panes-time
\ display-time history-limit lock-after-time lock-command lock-server
\ message-command-style message-limit message-style mouse-resize-pane
\ mouse-select-pane mouse-select-window mouse-utf8
\ pane-active-border-style pane-border-style prefix prefix2
\ display-time history-limit
\ lock-after-time lock-command lock-server
\ message-command-attr message-attr message-command-bg message-bg
\ message-command-fg message-fg message-limit
\ mouse-resize-pane mouse-select-pane mouse-select-window mouse-utf8
\ pane-active-border-bg pane-border-bg pane-active-border-fg
\ pane-border-fg prefix prefix2
\ renumber-windows repeat-time set-remain-on-exit set-titles
\ set-titles-string status status-interval status-justify status-keys
\ status-left status-left-length status-left-style status-position
\ status-right status-right-length staus-right-style status-utf8
\ terminal-overrides update-environment visual-activity visual-bell
\ visual-content visual-silence word-separators
\ set-titles-string status status-attr status-bg status-fg
\ status-interval status-justify status-keys status-left
\ status-left-attr status-left-bg status-left-fg status-left-length
\ status-position status-right status-right-attr status-right-bg
\ status-right-fg status-right-length status-utf8 terminal-overrides
\ update-environment visual-activity visual-bell visual-content
\ visual-silence word-separators
syn keyword tmuxOptsSetw
\ aggressive-resize allow-rename alternate-screen automatic-rename
\ aggressive-resize alternate-screen automatic-rename
\ c0-change-interval c0-change-trigger clock-mode-colour
\ clock-mode-style force-height force-width force-height
\ force-width main-pane-height main-pane-width mode-keys
\ mode-mouse mode-style monitor-activity monitor-content monitor-silence
\ clock-mode-style force-height force-width layout-history-limit
\ main-pane-height main-pane-width mode-attr mode-bg mode-fg move-keys
\ mode-mouse monitor-activity monitor-content monitor-silence
\ other-pane-height other-pane-width pane-base-index remain-on-exit
\ synchronize-panes utf8 window-status-activity-style
\ window-status-bell-style window-status-content-style
\ window-status-current-format window-status-current-style
\ window-status-format window-status-last-style window-status-separator
\ window-status-style wrap-search xterm-keys
\ synchronize-panes utf8 window-status-bell-attr window-status-bell-bg
\ window-status-bell-fg window-status-content-attr
\ window-status-content-bg window-status-content-fg
\ window-status-activity-attr window-status-activity-bg
\ window-status-activity-fg window-status-attr
\ window-status-current-attr window-status-attr window-status-current-bg
\ window-status-bg window-status-current-fg window-status-fg
\ window-status-current-format window-status-format
\ window-status-separator xterm-keys wrap-search
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
+53 -183
View File
@@ -18,8 +18,6 @@
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -34,10 +32,9 @@
* string.
*/
int format_replace(struct format_tree *, const char *, size_t, char **,
size_t *, size_t *);
char *format_get_command(struct window_pane *);
void format_window_pane_tabs(struct format_tree *, struct window_pane *);
int format_replace(struct format_tree *, const char *, size_t, char **,
size_t *, size_t *);
void format_window_pane_tabs(struct format_tree *, struct window_pane *);
/* Format key-value replacement entry. */
RB_GENERATE(format_tree, format_entry, entry, format_cmp);
@@ -49,8 +46,8 @@ format_cmp(struct format_entry *fe1, struct format_entry *fe2)
return (strcmp(fe1->key, fe2->key));
}
/* Single-character uppercase aliases. */
const char *format_upper[] = {
/* Single-character aliases. */
const char *format_aliases[26] = {
NULL, /* A */
NULL, /* B */
NULL, /* C */
@@ -79,52 +76,18 @@ const char *format_upper[] = {
NULL /* Z */
};
/* Single-character lowercase aliases. */
const char *format_lower[] = {
NULL, /* a */
NULL, /* b */
NULL, /* c */
NULL, /* d */
NULL, /* e */
NULL, /* f */
NULL, /* g */
"host_short", /* h */
NULL, /* i */
NULL, /* j */
NULL, /* k */
NULL, /* l */
NULL, /* m */
NULL, /* n */
NULL, /* o */
NULL, /* p */
NULL, /* q */
NULL, /* r */
NULL, /* s */
NULL, /* t */
NULL, /* u */
NULL, /* v */
NULL, /* w */
NULL, /* x */
NULL, /* y */
NULL /* z */
};
/* Create a new tree. */
struct format_tree *
format_create(void)
{
struct format_tree *ft;
char host[MAXHOSTNAMELEN], *ptr;
char host[MAXHOSTNAMELEN];
ft = xmalloc(sizeof *ft);
RB_INIT(ft);
if (gethostname(host, sizeof host) == 0) {
if (gethostname(host, sizeof host) == 0)
format_add(ft, "host", "%s", host);
if ((ptr = strchr(host, '.')) != NULL)
*ptr = '\0';
format_add(ft, "host_short", "%s", host);
}
return (ft);
}
@@ -146,7 +109,7 @@ format_free(struct format_tree *ft)
free(fe);
}
free(ft);
free (ft);
}
/* Add a key-value pair. */
@@ -154,7 +117,6 @@ void
format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
{
struct format_entry *fe;
struct format_entry *fe_now;
va_list ap;
fe = xmalloc(sizeof *fe);
@@ -164,13 +126,7 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
xvasprintf(&fe->value, fmt, ap);
va_end(ap);
fe_now = RB_INSERT(format_tree, ft, fe);
if (fe_now != NULL) {
free(fe_now->value);
fe_now->value = fe->value;
free(fe->key);
free(fe);
}
RB_INSERT(format_tree, ft, fe);
}
/* Find a format entry. */
@@ -191,40 +147,18 @@ format_find(struct format_tree *ft, const char *key)
* #{?blah,a,b} is replace with a if blah exists and is nonzero else b.
*/
int
format_replace(struct format_tree *ft, const char *key, size_t keylen,
char **buf, size_t *len, size_t *off)
format_replace(struct format_tree *ft,
const char *key, size_t keylen, char **buf, size_t *len, size_t *off)
{
char *copy, *copy0, *endptr, *ptr, *saved;
char *copy, *ptr;
const char *value;
size_t valuelen;
u_long limit = ULONG_MAX;
/* Make a copy of the key. */
copy0 = copy = xmalloc(keylen + 1);
copy = xmalloc(keylen + 1);
memcpy(copy, key, keylen);
copy[keylen] = '\0';
/* Is there a length limit or whatnot? */
if (!islower((u_char) *copy) && *copy != '?') {
while (*copy != ':' && *copy != '\0') {
switch (*copy) {
case '=':
errno = 0;
limit = strtoul(copy + 1, &endptr, 10);
if (errno == ERANGE && limit == ULONG_MAX)
goto fail;
copy = endptr;
break;
default:
copy++;
break;
}
}
if (*copy != ':')
goto fail;
copy++;
}
/*
* Is this a conditional? If so, check it exists and extract either the
* first or second element. If not, look up the key directly.
@@ -248,20 +182,13 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
goto fail;
value = ptr + 1;
}
saved = format_expand(ft, value);
value = saved;
} else {
value = format_find(ft, copy);
if (value == NULL)
value = "";
saved = NULL;
}
valuelen = strlen(value);
/* Truncate the value if needed. */
if (valuelen > limit)
valuelen = limit;
/* Expand the buffer and copy in the value. */
while (*len - *off < valuelen + 1) {
*buf = xrealloc(*buf, 2, *len);
@@ -270,12 +197,11 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
memcpy(*buf + *off, value, valuelen);
*off += valuelen;
free(saved);
free(copy0);
free(copy);
return (0);
fail:
free(copy0);
free(copy);
return (-1);
}
@@ -283,10 +209,10 @@ fail:
char *
format_expand(struct format_tree *ft, const char *fmt)
{
char *buf;
const char *ptr, *s;
char *buf, *ptr;
const char *s;
size_t off, len, n;
int ch, brackets;
int ch;
len = 64;
buf = xmalloc(len);
@@ -306,14 +232,8 @@ format_expand(struct format_tree *ft, const char *fmt)
ch = (u_char) *fmt++;
switch (ch) {
case '{':
brackets = 1;
for (ptr = fmt; *ptr != '\0'; ptr++) {
if (*ptr == '{')
brackets++;
if (*ptr == '}' && --brackets == 0)
break;
}
if (*ptr != '}' || brackets != 0)
ptr = strchr(fmt, '}');
if (ptr == NULL)
break;
n = ptr - fmt;
@@ -321,31 +241,23 @@ format_expand(struct format_tree *ft, const char *fmt)
break;
fmt += n + 1;
continue;
case '#':
while (len - off < 2) {
default:
if (ch >= 'A' && ch <= 'Z') {
s = format_aliases[ch - 'A'];
if (s != NULL) {
n = strlen(s);
if (format_replace (
ft, s, n, &buf, &len, &off) != 0)
break;
continue;
}
}
while (len - off < 3) {
buf = xrealloc(buf, 2, len);
len *= 2;
}
buf[off++] = '#';
continue;
default:
s = NULL;
if (ch >= 'A' && ch <= 'Z')
s = format_upper[ch - 'A'];
else if (ch >= 'a' && ch <= 'z')
s = format_lower[ch - 'a'];
if (s == NULL) {
while (len - off < 3) {
buf = xrealloc(buf, 2, len);
len *= 2;
}
buf[off++] = '#';
buf[off++] = ch;
continue;
}
n = strlen(s);
if (format_replace(ft, s, n, &buf, &len, &off) != 0)
break;
buf[off++] = ch;
continue;
}
@@ -356,26 +268,6 @@ format_expand(struct format_tree *ft, const char *fmt)
return (buf);
}
/* Get command name for format. */
char *
format_get_command(struct window_pane *wp)
{
char *cmd, *out;
cmd = osdep_get_name(wp->fd, wp->tty);
if (cmd == NULL || *cmd == '\0') {
free(cmd);
cmd = xstrdup(wp->cmd);
if (cmd == NULL || *cmd == '\0') {
free(cmd);
cmd = xstrdup(wp->shell);
}
}
out = parse_window_name(cmd);
free(cmd);
return (out);
}
/* Set default format keys for a session. */
void
format_session(struct format_tree *ft, struct session *s)
@@ -396,7 +288,7 @@ format_session(struct format_tree *ft, struct session *s)
format_add(ft, "session_group", "%u", session_group_index(sg));
t = s->creation_time.tv_sec;
format_add(ft, "session_created", "%lld", (long long) t);
format_add(ft, "session_created", "%ld", (long) t);
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
format_add(ft, "session_created_string", "%s", tim);
@@ -415,21 +307,20 @@ format_client(struct format_tree *ft, struct client *c)
time_t t;
struct session *s;
format_add(ft, "client_cwd", "%s", c->cwd);
format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL)
format_add(ft, "client_tty", "%s", c->tty.path);
if (c->tty.termname != NULL)
format_add(ft, "client_termname", "%s", c->tty.termname);
format_add(ft, "client_tty", "%s", c->tty.path);
format_add(ft, "client_termname", "%s", c->tty.termname);
t = c->creation_time.tv_sec;
format_add(ft, "client_created", "%lld", (long long) t);
format_add(ft, "client_created", "%ld", (long) t);
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
format_add(ft, "client_created_string", "%s", tim);
t = c->activity_time.tv_sec;
format_add(ft, "client_activity", "%lld", (long long) t);
format_add(ft, "client_activity", "%ld", (long) t);
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
format_add(ft, "client_activity_string", "%s", tim);
@@ -454,50 +345,28 @@ format_client(struct format_tree *ft, struct client *c)
format_add(ft, "client_last_session", "%s", s->name);
}
/* Set default format keys for a window. */
void
format_window(struct format_tree *ft, struct window *w)
{
char *layout;
layout = layout_dump(w);
format_add(ft, "window_id", "@%u", w->id);
format_add(ft, "window_name", "%s", w->name);
format_add(ft, "window_width", "%u", w->sx);
format_add(ft, "window_height", "%u", w->sy);
format_add(ft, "window_layout", "%s", layout);
format_add(ft, "window_panes", "%u", window_count_panes(w));
free(layout);
}
/* Set default format keys for a winlink. */
void
format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
{
struct window *w = wl->window;
char *flags;
char *layout, *flags;
layout = layout_dump(w);
flags = window_printable_flags(s, wl);
format_window(ft, w);
format_add(ft, "window_id", "@%u", w->id);
format_add(ft, "window_index", "%d", wl->idx);
format_add(ft, "window_name", "%s", w->name);
format_add(ft, "window_width", "%u", w->sx);
format_add(ft, "window_height", "%u", w->sy);
format_add(ft, "window_flags", "%s", flags);
format_add(ft, "window_layout", "%s", layout);
format_add(ft, "window_active", "%d", wl == s->curw);
format_add(ft, "window_bell_flag", "%u",
!!(wl->flags & WINLINK_BELL));
format_add(ft, "window_content_flag", "%u",
!!(wl->flags & WINLINK_CONTENT));
format_add(ft, "window_activity_flag", "%u",
!!(wl->flags & WINLINK_ACTIVITY));
format_add(ft, "window_silence_flag", "%u",
!!(wl->flags & WINLINK_SILENCE));
format_add(ft, "window_panes", "%u", window_count_panes(w));
free(flags);
free(layout);
}
/* Add window pane tabs. */
@@ -530,7 +399,8 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
struct grid_line *gl;
unsigned long long size;
u_int i, idx;
char *cmd, *cwd;
const char *cwd;
char *cmd;
size = 0;
for (i = 0; i < gd->hsize; i++) {
@@ -554,17 +424,17 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_dead", "%d", wp->fd == -1);
format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
format_add(ft, "pane_synchronized", "%d",
!!options_get_number(&wp->window->options, "synchronize-panes"));
if (wp->tty != NULL)
format_add(ft, "pane_tty", "%s", wp->tty);
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
if (wp->cmd != NULL)
format_add(ft, "pane_start_command", "%s", wp->cmd);
if (wp->cwd != NULL)
format_add(ft, "pane_start_path", "%s", wp->cwd);
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd);
if ((cmd = format_get_command(wp)) != NULL) {
if ((cmd = osdep_get_name(wp->fd, wp->tty)) != NULL) {
format_add(ft, "pane_current_command", "%s", cmd);
free(cmd);
}
+9 -11
View File
@@ -37,6 +37,7 @@
/* Default grid cell data. */
const struct grid_cell grid_default_cell = { 0, 0, 8, 8, (1 << 4) | 1, " " };
const struct grid_cell grid_marker_cell = { 0, 0, 8, 8, (1 << 4) | 1, "_" };
#define grid_put_cell(gd, px, py, gc) do { \
memcpy(&gd->linedata[py].celldata[px], \
@@ -123,7 +124,7 @@ grid_compare(struct grid *ga, struct grid *gb)
struct grid_cell *gca, *gcb;
u_int xx, yy;
if (ga->sx != gb->sx || ga->sy != gb->sy)
if (ga->sx != gb->sx || ga->sy != ga->sy)
return (1);
for (yy = 0; yy < ga->sy; yy++) {
@@ -267,7 +268,8 @@ grid_get_cell(struct grid *gd, u_int px, u_int py)
/* Set cell at relative position. */
void
grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
grid_set_cell(
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
{
if (grid_check_y(gd, py) != 0)
return;
@@ -590,7 +592,6 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
char *buf, code[128];
size_t len, off, size, codelen;
u_int xx;
const struct grid_line *gl;
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
@@ -603,11 +604,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
buf = xmalloc(len);
off = 0;
gl = grid_peek_line(gd, py);
for (xx = px; xx < px + nx; xx++) {
if (gl == NULL || xx >= gl->cellsize)
break;
gc = &gl->celldata[xx];
gc = grid_peek_cell(gd, xx, py);
if (gc->flags & GRID_FLAG_PADDING)
continue;
grid_cell_get(gc, &ud);
@@ -643,7 +641,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
if (trim) {
while (off > 0 && buf[off - 1] == ' ')
off--;
}
}
buf[off] = '\0';
return (buf);
@@ -655,8 +653,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
* available.
*/
void
grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
u_int ny)
grid_duplicate_lines(
struct grid *dst, u_int dy, struct grid *src, u_int sy, u_int ny)
{
struct grid_line *dstl, *srcl;
u_int yy;
@@ -749,7 +747,7 @@ grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
dst_gl->flags |= GRID_LINE_WRAPPED;
/* Copy the data. */
memcpy(&dst_gl->celldata[0], &src_gl->celldata[offset],
memcpy (&dst_gl->celldata[0], &src_gl->celldata[offset],
to_copy * sizeof dst_gl->celldata[0]);
/* Move offset and reduce old line size. */
+1 -1
View File
@@ -226,7 +226,7 @@ input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
len += utf8_split2(m->x + 33, &buf[len]);
len += utf8_split2(m->y + 33, &buf[len]);
} else {
if (m->xb > 223)
if (m->xb > 223 || m->x >= 222 || m->y > 222)
return;
len = xsnprintf(buf, sizeof buf, "\033[M");
buf[len++] = m->xb + 32;
+46 -148
View File
@@ -70,11 +70,6 @@ int input_input(struct input_ctx *);
int input_c0_dispatch(struct input_ctx *);
int input_esc_dispatch(struct input_ctx *);
int input_csi_dispatch(struct input_ctx *);
void input_csi_dispatch_rm(struct input_ctx *);
void input_csi_dispatch_rm_private(struct input_ctx *);
void input_csi_dispatch_sm(struct input_ctx *);
void input_csi_dispatch_sm_private(struct input_ctx *);
void input_csi_dispatch_winops(struct input_ctx *);
void input_csi_dispatch_sgr(struct input_ctx *);
int input_dcs_dispatch(struct input_ctx *);
int input_utf8_open(struct input_ctx *);
@@ -155,7 +150,6 @@ enum input_csi_type {
INPUT_CSI_SM_PRIVATE,
INPUT_CSI_TBC,
INPUT_CSI_VPA,
INPUT_CSI_WINOPS,
};
/* Control (CSI) command table. */
@@ -190,7 +184,6 @@ const struct input_table_entry input_csi_table[] = {
{ 'q', " ", INPUT_CSI_DECSCUSR },
{ 'r', "", INPUT_CSI_DECSTBM },
{ 's', "", INPUT_CSI_SCP },
{ 't', "", INPUT_CSI_WINOPS },
{ 'u', "", INPUT_CSI_RCP },
};
@@ -1078,9 +1071,10 @@ int
input_csi_dispatch(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
struct window_pane *wp = ictx->wp;
struct screen *s = sctx->s;
struct input_table_entry *entry;
int n, m;
int n, m;
if (ictx->flags & INPUT_DISCARD)
return (0);
@@ -1120,9 +1114,6 @@ input_csi_dispatch(struct input_ctx *ictx)
m = input_get(ictx, 1, 1, 1);
screen_write_cursormove(sctx, m - 1, n - 1);
break;
case INPUT_CSI_WINOPS:
input_csi_dispatch_winops(ictx);
break;
case INPUT_CSI_CUU:
screen_write_cursorup(sctx, input_get(ictx, 0, 1, 1));
break;
@@ -1239,60 +1230,7 @@ input_csi_dispatch(struct input_ctx *ictx)
screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
break;
case INPUT_CSI_RM:
input_csi_dispatch_rm(ictx);
break;
case INPUT_CSI_RM_PRIVATE:
input_csi_dispatch_rm_private(ictx);
break;
case INPUT_CSI_SCP:
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
ictx->old_cx = s->cx;
ictx->old_cy = s->cy;
break;
case INPUT_CSI_SGR:
input_csi_dispatch_sgr(ictx);
break;
case INPUT_CSI_SM:
input_csi_dispatch_sm(ictx);
break;
case INPUT_CSI_SM_PRIVATE:
input_csi_dispatch_sm_private(ictx);
break;
case INPUT_CSI_TBC:
switch (input_get(ictx, 0, 0, 0)) {
case 0:
if (s->cx < screen_size_x(s))
bit_clear(s->tabs, s->cx);
break;
case 3:
bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
break;
case INPUT_CSI_VPA:
n = input_get(ictx, 0, 1, 1);
screen_write_cursormove(sctx, s->cx, n - 1);
break;
case INPUT_CSI_DECSCUSR:
n = input_get(ictx, 0, 0, 0);
screen_set_cursor_style(s, n);
break;
}
return (0);
}
/* Handle CSI RM. */
void
input_csi_dispatch_rm(struct input_ctx *ictx)
{
u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
switch (input_get(ictx, i, 0, -1)) {
switch (input_get(ictx, 0, 0, -1)) {
case 4: /* IRM */
screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
break;
@@ -1300,18 +1238,10 @@ input_csi_dispatch_rm(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
}
}
/* Handle CSI private RM. */
void
input_csi_dispatch_rm_private(struct input_ctx *ictx)
{
u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
switch (input_get(ictx, i, 0, -1)) {
case 1: /* DECCKM */
break;
case INPUT_CSI_RM_PRIVATE:
switch (input_get(ictx, 0, 0, -1)) {
case 1: /* GATM */
screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
break;
case 3: /* DECCOLM */
@@ -1341,10 +1271,10 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
break;
case 47:
case 1047:
window_pane_alternate_off(ictx->wp, &ictx->cell, 0);
window_pane_alternate_off(wp, &ictx->cell, 0);
break;
case 1049:
window_pane_alternate_off(ictx->wp, &ictx->cell, 1);
window_pane_alternate_off(wp, &ictx->cell, 1);
break;
case 2004:
screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
@@ -1353,17 +1283,17 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
}
}
/* Handle CSI SM. */
void
input_csi_dispatch_sm(struct input_ctx *ictx)
{
u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
switch (input_get(ictx, i, 0, -1)) {
break;
case INPUT_CSI_SCP:
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
ictx->old_cx = s->cx;
ictx->old_cy = s->cy;
break;
case INPUT_CSI_SGR:
input_csi_dispatch_sgr(ictx);
break;
case INPUT_CSI_SM:
switch (input_get(ictx, 0, 0, -1)) {
case 4: /* IRM */
screen_write_mode_set(&ictx->ctx, MODE_INSERT);
break;
@@ -1371,18 +1301,10 @@ input_csi_dispatch_sm(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
}
}
/* Handle CSI private SM. */
void
input_csi_dispatch_sm_private(struct input_ctx *ictx)
{
u_int i;
for (i = 0; i < ictx->param_list_len; i++) {
switch (input_get(ictx, i, 0, -1)) {
case 1: /* DECCKM */
break;
case INPUT_CSI_SM_PRIVATE:
switch (input_get(ictx, 0, 0, -1)) {
case 1: /* GATM */
screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
break;
case 3: /* DECCOLM */
@@ -1408,10 +1330,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY);
break;
case 1004:
if (ictx->ctx.s->mode & MODE_FOCUSON)
if (s->mode & MODE_FOCUSON)
break;
screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
ictx->wp->flags |= PANE_FOCUSPUSH; /* force update */
wp->flags &= ~PANE_FOCUSED; /* force update if needed */
break;
case 1005:
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
@@ -1421,10 +1343,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
break;
case 47:
case 1047:
window_pane_alternate_on(ictx->wp, &ictx->cell, 0);
window_pane_alternate_on(wp, &ictx->cell, 0);
break;
case 1049:
window_pane_alternate_on(ictx->wp, &ictx->cell, 1);
window_pane_alternate_on(wp, &ictx->cell, 1);
break;
case 2004:
screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
@@ -1433,56 +1355,32 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
}
}
/* Handle CSI window operations. */
void
input_csi_dispatch_winops(struct input_ctx *ictx)
{
struct window_pane *wp = ictx->wp;
int n, m;
m = 0;
while ((n = input_get(ictx, m, 0, -1)) != -1) {
switch (n) {
case 1:
case 2:
case 5:
case 6:
case 7:
case 11:
case 13:
case 14:
case 19:
case 20:
case 21:
case 24:
break;
case INPUT_CSI_TBC:
switch (input_get(ictx, 0, 0, 0)) {
case 0:
if (s->cx < screen_size_x(s))
bit_clear(s->tabs, s->cx);
break;
case 3:
case 4:
case 8:
m++;
if (input_get(ictx, m, 0, -1) == -1)
return;
/* FALLTHROUGH */
case 9:
case 10:
case 22:
case 23:
m++;
if (input_get(ictx, m, 0, -1) == -1)
return;
break;
case 18:
input_reply(ictx, "\033[8;%u;%u", wp->sy, wp->sx);
bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
}
m++;
break;
case INPUT_CSI_VPA:
n = input_get(ictx, 0, 1, 1);
screen_write_cursormove(sctx, s->cx, n - 1);
break;
case INPUT_CSI_DECSCUSR:
n = input_get(ictx, 0, 0, 0);
screen_set_cursor_style(s, n);
break;
}
return (0);
}
/* Handle CSI SGR. */

Some files were not shown because too many files have changed in this diff Show More