1 Commits
1.7 ... 1.5

Author SHA1 Message Date
Tiago Cunha
509c63b618 Tag 1.5 release. 2011-07-09 16:10:35 +00:00
155 changed files with 3231 additions and 8211 deletions

12
.gitignore vendored
View File

@@ -1,12 +0,0 @@
*.o
*~
.deps/
aclocal.m4
autom4te.cache/
config.log
config.status
etc/
tmux
Makefile
Makefile.in
configure

110
CHANGES
View File

@@ -1,113 +1,3 @@
CHANGES FROM 1.6 to 1.7, 13 October 2012
* tmux configuration files now support line-continuation with a "\" at the
end of a line.
* New option status-position to move the status line to the top or bottom of
the screen.
* Enforce history-limit option when clearing the screen.
* Give each window a unique id, like panes but prefixed with @.
* Add pane id to each pane in layout description (while still accepting
the old form).
* Provide defined ways to set the various default-path possibilities: ~
for home directory, . for server start directory, - for session start
directory and empty for the pane's working directory (the default). All
can also be used as part of a relative path (eg -/foo). Also provide -c
flags to neww and splitw to override default-path setting.
* Add -l flag to send-keys to send input literally (without translating
key names).
* Allow a single option to be specified to show-options to show just that
option.
* New command "move-pane" (like join-pane but allows the same window).
* join-pane and move-pane commands learn "-b" option to place the pane to
the left or above.
* Support for bracketed-paste mode.
* Allow send-keys command to accept hex values.
* Add locking around "start-server" to avoid race-conditions.
* break-pane learns -P/-F arguments for display formatting.
* set-option learns "-q" to make it quiet, and not print out anything.
* copy mode learns "wrap-search" option.
* Add a simple form of output rate limiting by counting the number of
certain C0 sequences (linefeeds, backspaces, carriage returns) and if it
exceeds a threshold (current default 250/millisecond), start to redraw
the pane every 100 milliseconds instead of making each change as it
comes. Two configuration options - c0-change-trigger and
c0-change-interval.
* find-window learns new flags: "-C", "-N", "-T" to match against either or
all of a window's content, name, or title. Defaults to all three options
if none specified.
* find-window automatically selects the appropriate pane for the found
matches.
* show-environment can now accept one option to show that environment value.
* Exit mouse mode when end-of-screen reached when scrolling with the mouse
wheel.
* select-layout learns -u and -U for layout history stacks.
* kill-window, detach-client, kill-session all learn "-a" option for
killing all but the current thing specified.
* move-window learns "-r" option to renumber window sequentially in a
session.
* New session option "renumber-windows" to automatically renumber windows in
a session when a window is closed. (see "move-window -r").
* Only enter copy-mode on scroll up.
* choose-* and list-* commands all use "-F" for format specifiers.
* When spawning external commands, the value from the "default-shell" option
is now used, rather than assuming /bin/sh.
* New choose-tree command to render window/sessions as a tree for selection.
* display-message learns new format options.
* For linked-windows across sessions, all flags for that window are now
cleared across sessions.
* Lots and lots of bug fixes, fixing memory-leaks, etc.
* Various manpage improvements.
CHANGES FROM 1.5 TO 1.6, 23 January 2012
* Extend the mode-mouse option to add a third choice which means the mouse
does not enter copy mode.
* Add a -r flag to switch-client to toggle the client read-only flag.
* Add pane-base-index option.
* Support \ for line continuation in the configuration file.
* Framework for more powerful formatting of command output and use it for
list-{panes,windows,sessions}. This allows more descriptive replacements
(such as #{session_name}) and conditionals.
* Mark dead panes with some text saying they are dead.
* Reject $SHELL if it is not a full path.
* Add -S option to refresh-client to redraw status line.
* Add an else clause for if-shell.
* Try to resolve relative paths for loadb and saveb (first, using client
working directory, if any, then default-path or session working directory).
* Support for \e[3J to clear the history and send the corresponding
terminfo code (E3) before locking.
* When in copy mode, make repeat count indicate buffer to replace, if used.
* Add screen*:XT to terminal-overrides for tmux-in-tmux.
* Status-line message attributes added.
* Move word-separators to be a session rather than window option.
* Change the way the working directory for new processes is discovered. If
default-path isn't empty, it is used. Otherwise, if a new window is created
from the command-line, the working directory of the client is used. If not,
platform specific code is used to retrieve the current working directory
of the process in the active pane. If that fails, the directory where the
session was created is used, instead.
* Do not change the current pane if both mouse-select-{pane,window} are
enabled.
* Add \033[s and \033[u to save and restore cursor position.
* Allow $HOME to be used as default-path.
* Add CNL and CPL escape sequences.
* Calculate last position correctly for UTF-8 wide characters.
* Add an option allow-rename to disable the window rename escape sequence.
* Attributes for each type of status-line alert (ie bell, content and
activity) added. Therefore, remove the superfluous options
window-status-alert-{attr,bg,fg}.
* Add a -R flag to send-keys to reset the terminal.
* Add strings to allow the aixterm bright colours to be used when
configuring colours.
* Drop the ability to have a list of keys in the prefix in favour of two
separate options, prefix and prefix2.
* Flag -2 added to send-prefix to send the secondary prefix key.
* Show pane size in top right of display panes mode.
* Some memory leaks plugged.
* More command-prompt editing improvements.
* Various manpage improvements.
* More Vi mode improvements.
CHANGES FROM 1.4 TO 1.5, 09 July 2011
* Support xterm mouse modes 1002 and 1003.

32
FAQ
View File

@@ -409,37 +409,5 @@ If your urxvt cannot display italics at all, make sure you have an italics
capable font enabled, for example, add to ~/.Xdefaults:
urxvt.italicFont: xft:Bitstream Vera Sans Mono:italic:autohint=true
* How can I make tmux use my terminal's scrollback buffer?
Normally, tmux enables the terminal's "alternate screen". Most terminals (such
as xterm) do not save scrollback for the alternate screen. You might prefer
tmux to use the normal screen, so it uses your terminal's scrollback
buffer. This way, you can access the scrollback buffer as usual, for example
using the mouse wheel - although there is no guarantee output inside tmux will
always (or ever) be added to the scrollback.
You can make tmux use the normal screen by telling it that your terminal does
not have an alternate screen. Put the following in ~/.tmux.conf:
set -g terminal-overrides 'xterm*:smcup@:rmcup@'
Adjust if your $TERM does not start with xterm.
tmux will still emulate the alternate screen for applications run under tmux,
so you don't really lose anything with this setting. The only disadvantage is
that when you exit tmux, it will not restore whatever was there before you
started.
* How do I see the default configuration?
Show the default session options by starting a new tmux server with no
configuration file:
$ tmux -Lfoo -f/dev/null start\; show -g
Or the default window options:
$ tmux -Lfoo -f/dev/null start\; show -gw
$Id$

View File

@@ -43,6 +43,11 @@ CPPFLAGS += -I. -I- -I/usr/local/include
endif
endif
# Set flags for static.
if IS_STATIC
LDFLAGS += -static
endif
# Set flags for Solaris.
if IS_SUNOS
CPPFLAGS += -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
@@ -66,8 +71,8 @@ dist_tmux_SOURCES = \
cmd-capture-pane.c \
cmd-choose-buffer.c \
cmd-choose-client.c \
cmd-choose-list.c \
cmd-choose-tree.c \
cmd-choose-session.c \
cmd-choose-window.c \
cmd-clear-history.c \
cmd-clock-mode.c \
cmd-command-prompt.c \
@@ -135,10 +140,7 @@ dist_tmux_SOURCES = \
cmd-unlink-window.c \
cmd.c \
colour.c \
control.c \
control-notify.c \
environ.c \
format.c \
grid-utf8.c \
grid-view.c \
grid.c \
@@ -153,7 +155,6 @@ dist_tmux_SOURCES = \
log.c \
mode-key.c \
names.c \
notify.c \
options-table.c \
options.c \
paste.c \
@@ -225,9 +226,6 @@ endif
if NO_STRTONUM
nodist_tmux_SOURCES += compat/strtonum.c
endif
if NO_B64_NTOP
nodist_tmux_SOURCES += compat/b64_ntop.c
endif
# Update SF web site.
upload-index.html: update-index.html

53
NOTES
View File

@@ -5,67 +5,60 @@ 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).
run on Solaris and AIX (although they haven't been tested in a while). It is
usable, although there remain a number of missing features and some remaining
bugs are expected.
Since the 1.2 release tmux depends on libevent. Download it from:
Since the 1.2 release that tmux depends on libevent. Download it from:
http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
tmux consists of a server part and multiple clients. The server is created when
required and runs continuously unless killed by the user. Clients access the
server through a socket in /tmp. Multiple sessions may be created on a single
server and attached to a number of clients. Each session may then have a number
of windows and windows may be linked to a number of sessions. Commands are
available to create, rename and destroy windows and sessions; to attach and
detach sessions from client terminals; to set configuration options; to split
windows into several simultaneously displayed panes; and to bind and unbind
command keys (invoked preceded by a prefix key, by default ctrl-b). Please see
the tmux(1) man page for further information.
$ ./configure && make
$ sudo make install
A more extensive, but rough, todo list is included in the TODO file.
To get and build the latest version control checkout:
$ git clone git://tmux.git.sourceforge.net/gitroot/tmux/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.
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.
tmux also depends on several features of the client terminal (TERM), if these
are missing it may refuse to run, or not behave correctly.
A Vim syntax file is available in the examples directory. To install it:
- Drop the file in the syntax directory into runtimepath (such as
- Drop the file in the syntax directory in your runtimepath (such as
~/.vim/syntax/tmux.vim).
- Make the filetype recognisable by adding the following to filetype.vim
(~/.vim/filetype.vim):
in your runtimepath (~/.vim/filetype.vim):
augroup filetypedetect
au BufNewFile,BufRead .tmux.conf*,tmux.conf* setf tmux
augroup END
- Switch on syntax highlighting by adding "syntax enable" to .vimrc.
- Switch on syntax highlighting by adding "syntax enable" to your vimrc file.
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
tmux mailing lists are available. The visit:
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
nicm@users.sf.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.
start. Please contact me with any queries.
-- Nicholas Marriott <nicm@users.sf.net>

173
SYNCING
View File

@@ -1,173 +0,0 @@
Preamble
========
Tmux on SourceForge has two git repositories [1] "tmux" and "tmux-openbsd".
Here's a description of them:
* "tmux" is the portable version, the one which contains code for other
operating systems, and autotools, etc., which isn't found or needed in the
OpenBSD base system.
* "tmux-openbsd" is the version of tmux in OpenBSD base system which provides
the basis of the portable tmux version.
Note: The "tmux-openbsd" repository is actually handled by "git cvsimport"
running at 15 minute intervals, so a commit made to OpenBSD's tmux CVS
repository will take that long to appear in this git repository.
It is assumed that the person doing the sync has read/write access to the
tmux repository on SourceForge already.
If you've never used git before, git tracks meta-data about the committer
and the author, as part of a commit, hence:
% git config [--global] user.name "Your name"
% git config [--global] user.email "you@yourdomain.com"
Note that, if you already have this in the global ~/.gitconfig option, then
this will be used. Setting this per-repository would involve not using the
"--global" flag above. If you wish to use the same credentials always,
pass the "--global" option, as shown.
This is a one-off operation once the repository has been cloned, assuming
this information has ever been set before.
Cloning repositories
====================
This involves having both tmux and tmux-openbsd cloned, as in:
% cd /some/where/useful
% git clone ssh://${USER}@tmux.git.sf.net/gitroot/tmux/tmux
% git clone ssh://${USER}@tmux.git.sf.net/gitroot/tmux/tmux-openbsd
Note that you do not need additoinal checkouts to manage the sync -- an
existing clone of either repositories will suffice. So if you already have
these checkouts existing, skip that.
Adding in git-remotes
=====================
Because the portable "tmux" git repository and the "tmux-openbsd" repository do
not inherently share any history between each other, the history has been
faked between them. This "faking of history" is something which has to be
told to git for the purposes of comparing the "tmux" and "tmux-openbsd"
repositories for syncing. To do this, we must reference the clone of the
"tmux-openbsd" repository from the "tmux" repository, as shown by the
following command:
% cd /path/to/tmux
% git remote add obsd-tmux file:///path/to/tmux-openbsd
So that now, the remote "obsd-tmux" can be used to reference branches and
commits from the "tmux-openbsd" repository, but from the context of the
portable "tmux" repository, which makes sense because it's the "tmux"
repository which will have the updates applied to them.
Fetching updates
================
To ensure the latest commits from "tmux-openbsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-openbsd" is
up-to-date first, and then reference that update in "tmux", as in:
% cd /path/to/tmux-openbsd
% git checkout master
% git pull
Then back in "tmux":
% cd /path/to/tmux
% git fetch obsd-tmux
Creating the necessary branches
===============================
Now that "tmux" can see commits and branches from "tmux-openbsd" by way of
the remote name "obsd-tmux", we can now create the master branch from
"tmux-openbsd" in the "tmux" repository:
% git checkout -b obsd-master obsd-tmux/master
Adding in the fake history points
=================================
To tie both the "master" branch from "tmux" and the "obsd-master" branch
from "tmux-openbsd" together, the fake history points added to the "tmux"
repository need to be added. To do this, we must add an additional refspec
line, as in:
% cd /path/to/tmux
% git config --add remote.origin.fetch '+refs/replace/*:refs/replace/*'
% git fetch origin
Performing the Sync
===================
Make sure the "master" branch is checked out:
% git checkout master
The following will show commits on OpenBSD not yet synched with tmux
portable:
% git log master..obsd-master
From there, merge the result in, fixing up any conflicts which might arise.
% git merge obsd-master
Then ensure things look correct by BULDING the result of that sync:
% make clean && ./autogen.sh && ./configure && make
Compare the git merge result with what's on origin/master -- that is, check
which commits you're about to push:
% git log origin/master..master
And if happy:
% git push origin master
Release tmux for next version
=============================
1. Comment the "found_debug=yes" line in configure.ac, since releases
don't have debugging enabled, otherwise make(1) aborts when
preparing the distribution.
2. Update and commit NOTES and CHANGES. The former should be checked for
anything outdated and updated with a list of things that might break
upgrades and the latter should mention all the major changes since
the last version.
3. Tag with:
% git tag -a 1.X
Where "1.X" is the next version.
Push the tag out with:
% git push --tags
4. Build the tarball with make dist. Now that it's using autoconf there
shouldn't be any weird files (such as the original and rejection files
from patch(1)) but it doesn't hurt taking a quick look at it.
5. Split the release changes into a new file. This should be named
tmux-$VERSION-readme to make sourceforge show it automagically in specific
parts of the project page.
6. Upload the tarball and the above file. Make the tarball the default
download by selecting all operating systems under the file details.
7. Run make update-index.html upload-index.html to replace %%VERSION%%.
8. Bump version in configure.ac and uncomment "found_debug=yes" to create
a debug build by default.
9. Update freshmeat.
[1] http://tmux.git.sourceforge.net/git/gitweb-index.cgi

76
TODO
View File

@@ -1,19 +1,3 @@
NOTES
=====
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.
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.
Thie file is split up between tmux user interface (UI) issues, and terminal
compatibility issues.
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
@@ -22,10 +6,13 @@ TMUX UI ISSUES
- 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?
- next prev word etc in command prompt
- use a better termcap internally instead of screen, perhaps xterm
- 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?
- clear window title on exit
- 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
@@ -35,6 +22,7 @@ TMUX UI ISSUES
- 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
- get it passing all the vttest tests that don't require resizing the terminal
- way to set socket path from config file
- what about utmp etc? can tmux update it like screen? setgid?
- warts on current naming:
@@ -46,6 +34,7 @@ TMUX UI ISSUES
- a way for force-width/height to apply to only one pane (how?)
- command to list what is actually running in each window with command line,
pid (need some adaption of the osdep code)
- support for bce
- 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
@@ -67,14 +56,18 @@ TMUX UI ISSUES
- selection behaviour closer to vi in vi mode
- live update: server started with -U connects to server, requests sessions and
windows, receives fds
- command to show a tree of sessions-windows-panes (active marked with *)
- 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
- use screen-256color when started on 256 colour terminal??
- if-shell/run-shell should block further command execution in the same command
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)
- allow buffer to be specified when copying in copy mode
- multiline status line (no?)
- flag for absolute pane size to resize-pane
- sanity check input to socket
@@ -89,6 +82,7 @@ TMUX UI ISSUES
- ' 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
- why are alerts per-winlink? try per window?
- 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)
@@ -96,6 +90,7 @@ TMUX UI ISSUES
- synchronous commands - client sends cmd and blocks, neww/splitw saves client
ptr then when program inside died, sends MSG_SOMETHING with wait status to
client
- documentation improvements - rlpowell's tutorial - build instructions
- 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
@@ -105,6 +100,8 @@ TMUX UI ISSUES
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
- pane-index option like base-index
- option to move status line to top
- 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)
@@ -114,57 +111,30 @@ TMUX UI ISSUES
key is looked up in that table
- pass shell commands as argv rather than strings, allow them to be specified
in commands without quotes
- a command to choose from a generic list, so you can do eg
choose-list -l Abc,Moo,Blah "run-shell 'sh /my/choose/script %%'"
- else part for if-shell
- add general internal format for lists (key=value) and a way to output them in
different representations, use for list-windows, etc etc. see message id
20110221205346.GA1580@yelena.nicm.ath.cx
- numeric prefix in copy mode should be paste buffer for C-w
- named buffers and allow gaps in the stack
- npage/ppage/dc/ic should have aliases for more typical names
- get rid of separate UTF-8 cell stuff: add 1 byte to cell and store BMP as
uint16_t+3 bits of flags. anything <=0xffff is Unicode, higher are used to
build tree of combined characters/non-BMP (LRU dropped when full)
- entry in FAQ about what to do when someone does mkdir /tmp/tmux-1000
- show size under pane number in display-panes mode
- 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
- Support for borderless panes
- run-shell/if-shell should support status_replace stuff
- wait-pane command or another way to make it synchronous/wait for command to
finish
- way to get command window was started with (part of format stuff?)
- last-pane across sessions
- attach should take a pane and select it as well as attaching
- 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 certaing 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? TA to investigate.
- 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.
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??
- if-shell/run-shell should block further command execution in the same command
- possibly support rxvt-unicode extended mouse input (1015)
- wrap/no wrap esc seq DEC CSI ? 7 h/l
* 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!

View File

@@ -68,14 +68,15 @@ args_parse(const char *template, int argc, char **argv)
if (opt < 0 || opt >= SCHAR_MAX)
continue;
if (opt == '?' || (ptr = strchr(template, opt)) == NULL) {
free(args->flags);
free(args);
xfree(args->flags);
xfree(args);
return (NULL);
}
bit_set(args->flags, opt);
if (ptr[1] == ':') {
free(args->values[opt]);
if (args->values[opt] != NULL)
xfree(args->values[opt]);
args->values[opt] = xstrdup(optarg);
}
}
@@ -96,11 +97,13 @@ args_free(struct args *args)
cmd_free_argv(args->argc, args->argv);
for (i = 0; i < SCHAR_MAX; i++)
free(args->values[i]);
for (i = 0; i < SCHAR_MAX; i++) {
if (args->values[i] != NULL)
xfree(args->values[i]);
}
free(args->flags);
free(args);
xfree(args->flags);
xfree(args);
}
/* Print a set of arguments. */
@@ -179,7 +182,8 @@ args_has(struct args *args, u_char ch)
void
args_set(struct args *args, u_char ch, const char *value)
{
free(args->values[ch]);
if (args->values[ch] != NULL)
xfree(args->values[ch]);
if (value != NULL)
args->values[ch] = xstrdup(value);
else

View File

@@ -109,12 +109,13 @@
} while (0)
#define ARRAY_FREE(a) do { \
free((a)->list); \
if ((a)->list != NULL) \
xfree((a)->list); \
ARRAY_INIT(a); \
} while (0)
#define ARRAY_FREEALL(a) do { \
ARRAY_FREE(a); \
free(a); \
xfree(a); \
} while (0)
#endif

View File

@@ -26,21 +26,27 @@ const char *
attributes_tostring(u_char attr)
{
static char buf[128];
size_t len;
if (attr == 0)
return ("none");
len = xsnprintf(buf, sizeof buf, "%s%s%s%s%s%s%s",
attr & GRID_ATTR_BRIGHT ? "bright," : "",
attr & GRID_ATTR_DIM ? "dim," : "",
attr & GRID_ATTR_UNDERSCORE ? "underscore," : "",
attr & GRID_ATTR_BLINK ? "blink," : "",
attr & GRID_ATTR_REVERSE ? "reverse," : "",
attr & GRID_ATTR_HIDDEN ? "hidden," : "",
attr & GRID_ATTR_ITALICS ? "italics," : "");
if (len > 0)
buf[len - 1] = '\0';
buf[0] = '\0';
if (attr & GRID_ATTR_BRIGHT)
strlcat(buf, "bright,", sizeof (buf));
if (attr & GRID_ATTR_DIM)
strlcat(buf, "dim,", sizeof (buf));
if (attr & GRID_ATTR_UNDERSCORE)
strlcat(buf, "underscore,", sizeof (buf));
if (attr & GRID_ATTR_BLINK)
strlcat(buf, "blink,", sizeof (buf));
if (attr & GRID_ATTR_REVERSE)
strlcat(buf, "reverse,", sizeof (buf));
if (attr & GRID_ATTR_HIDDEN)
strlcat(buf, "hidden,", sizeof (buf));
if (attr & GRID_ATTR_ITALICS)
strlcat(buf, "italics,", sizeof (buf));
if (*buf != '\0')
*(strrchr(buf, ',')) = '\0';
return (buf);
}

0
autogen.sh Executable file → Normal file
View File

62
cfg.c
View File

@@ -21,7 +21,6 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -81,7 +80,7 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
size_t len;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
enum cmd_retval retval;
int retval;
if ((f = fopen(path, "rb")) == NULL) {
cfg_add_cause(causes, "%s: %s", path, strerror(errno));
@@ -90,42 +89,25 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
n = 0;
line = NULL;
retval = CMD_RETURN_NORMAL;
retval = 0;
while ((buf = fgetln(f, &len))) {
if (buf[len - 1] == '\n')
len--;
if (line != NULL)
line = xrealloc(line, 1, strlen(line) + len + 1);
buf[len - 1] = '\0';
else {
line = xmalloc(len + 1);
*line = '\0';
line = xrealloc(line, 1, len + 1);
memcpy(line, buf, len);
line[len] = '\0';
buf = line;
}
/* Append buffer to line. strncat will terminate. */
strncat(line, buf, len);
n++;
/* Continuation: get next line? */
len = strlen(line);
if (len > 0 && line[len - 1] == '\\') {
line[len - 1] = '\0';
/* Ignore escaped backslash at EOL. */
if (len > 1 && line[len - 2] != '\\')
continue;
}
buf = line;
line = NULL;
if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
free(buf);
if (cause == NULL)
continue;
cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
free(cause);
xfree(cause);
continue;
} else
free(buf);
}
if (cmdlist == NULL)
continue;
cfg_cause = NULL;
@@ -145,30 +127,16 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
ctx.info = cfg_print;
cfg_cause = NULL;
switch (cmd_list_exec(cmdlist, &ctx)) {
case CMD_RETURN_YIELD:
if (retval != CMD_RETURN_ATTACH)
retval = CMD_RETURN_YIELD;
break;
case CMD_RETURN_ATTACH:
retval = CMD_RETURN_ATTACH;
break;
case CMD_RETURN_ERROR:
case CMD_RETURN_NORMAL:
break;
}
if (cmd_list_exec(cmdlist, &ctx) == 1)
retval = 1;
cmd_list_free(cmdlist);
if (cfg_cause != NULL) {
cfg_add_cause(
causes, "%s: %d: %s", path, n, cfg_cause);
free(cfg_cause);
cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause);
xfree(cfg_cause);
}
}
if (line != NULL) {
cfg_add_cause(causes,
"%s: %d: line continuation at end of file", path, n);
free(line);
}
if (line != NULL)
xfree(line);
fclose(f);
return (retval);

241
client.c
View File

@@ -17,7 +17,6 @@
*/
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
@@ -35,58 +34,20 @@
struct imsgbuf client_ibuf;
struct event client_event;
struct event client_stdin;
enum {
CLIENT_EXIT_NONE,
CLIENT_EXIT_DETACHED,
CLIENT_EXIT_DETACHED_HUP,
CLIENT_EXIT_LOST_TTY,
CLIENT_EXIT_TERMINATED,
CLIENT_EXIT_LOST_SERVER,
CLIENT_EXIT_EXITED,
CLIENT_EXIT_SERVER_EXITED,
} client_exitreason = CLIENT_EXIT_NONE;
const char *client_exitmsg;
int client_exitval;
enum msgtype client_exittype;
int client_attached;
int client_get_lock(char *);
int client_connect(char *, int);
void client_send_identify(int);
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 *);
void client_write(int, const char *, size_t);
void client_callback(int, short, void *);
int client_dispatch_attached(void);
int client_dispatch_wait(void *);
const char *client_exit_message(void);
/*
* Get server create lock. If already held then server start is happening in
* another client, so block until the lock is released and return -1 to
* retry. Ignore other errors - just continue and start the server without the
* lock.
*/
int
client_get_lock(char *lockfile)
{
int lockfd;
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1)
fatal("open failed");
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) {
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
/* nothing */;
close(lockfd);
return (-1);
}
return (lockfd);
}
/* Connect client to server. */
int
@@ -94,8 +55,7 @@ client_connect(char *path, int start_server)
{
struct sockaddr_un sa;
size_t size;
int fd, lockfd;
char *lockfile;
int fd;
memset(&sa, 0, sizeof sa);
sa.sun_family = AF_UNIX;
@@ -105,25 +65,24 @@ client_connect(char *path, int start_server)
return (-1);
}
retry:
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket failed");
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
if (errno != ECONNREFUSED && errno != ENOENT)
goto failed;
if (!start_server)
goto failed;
close(fd);
xasprintf(&lockfile, "%s.lock", path);
if ((lockfd = client_get_lock(lockfile)) == -1)
goto retry;
if (unlink(path) != 0 && errno != ENOENT)
return (-1);
fd = server_start(lockfd, lockfile);
free(lockfile);
close(lockfd);
switch (errno) {
case ECONNREFUSED:
if (unlink(path) != 0)
goto failed;
/* FALLTHROUGH */
case ENOENT:
if ((fd = server_start()) == -1)
goto failed;
break;
default:
goto failed;
}
}
setblocking(fd, 0);
@@ -134,31 +93,6 @@ failed:
return (-1);
}
/* Get exit string from reason number. */
const char *
client_exit_message(void)
{
switch (client_exitreason) {
case CLIENT_EXIT_NONE:
break;
case CLIENT_EXIT_DETACHED:
return ("detached");
case CLIENT_EXIT_DETACHED_HUP:
return ("detached and SIGHUP");
case CLIENT_EXIT_LOST_TTY:
return ("lost tty");
case CLIENT_EXIT_TERMINATED:
return ("terminated");
case CLIENT_EXIT_LOST_SERVER:
return ("lost server");
case CLIENT_EXIT_EXITED:
return ("exited");
case CLIENT_EXIT_SERVER_EXITED:
return ("server exited");
}
return ("unknown reason");
}
/* Client main loop. */
int
client_main(int argc, char **argv, int flags)
@@ -170,7 +104,6 @@ client_main(int argc, char **argv, int flags)
pid_t ppid;
enum msgtype msg;
char *cause;
struct termios tio, saved_tio;
/* Set up the initial command. */
cmdflags = 0;
@@ -189,7 +122,7 @@ client_main(int argc, char **argv, int flags)
* flag.
*/
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
fprintf(stderr, "%s\n", cause);
log_warnx("%s", cause);
return (1);
}
cmdflags &= ~CMD_STARTSERVER;
@@ -209,17 +142,16 @@ client_main(int argc, char **argv, int flags)
* if the socket path matches $TMUX, this is probably the same server.
*/
if (shell_cmd == NULL && environ_path != NULL &&
(cmdflags & CMD_CANTNEST) &&
strcmp(socket_path, environ_path) == 0) {
fprintf(stderr, "sessions should be nested with care, "
"unset $TMUX to force\n");
cmdflags & CMD_CANTNEST && strcmp(socket_path, environ_path) == 0) {
log_warnx("sessions should be nested with care. "
"unset $TMUX to force.");
return (1);
}
/* 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\n");
log_warn("failed to connect to server");
return (1);
}
@@ -233,30 +165,6 @@ client_main(int argc, char **argv, int flags)
imsg_init(&client_ibuf, fd);
event_set(&client_event, fd, EV_READ, client_callback, shell_cmd);
/* Create stdin handler. */
setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
client_stdin_callback, NULL);
if (flags & IDENTIFY_TERMIOS) {
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
fprintf(stderr, "tcgetattr failed: %s\n",
strerror(errno));
return (1);
}
cfmakeraw(&tio);
tio.c_iflag = ICRNL|IXANY;
tio.c_oflag = OPOST|ONLCR;
#ifdef NOKERNINFO
tio.c_lflag = NOKERNINFO;
#endif
tio.c_cflag = CREAD|CS8|HUPCL;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
cfsetispeed(&tio, cfgetispeed(&saved_tio));
cfsetospeed(&tio, cfgetospeed(&saved_tio));
tcsetattr(STDIN_FILENO, TCSANOW, &tio);
}
/* Establish signal handlers. */
set_signals(client_signal);
@@ -275,7 +183,7 @@ client_main(int argc, char **argv, int flags)
cmddata.argc = argc;
if (cmd_pack_argv(
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
fprintf(stderr, "command too long\n");
log_warnx("command too long");
return (1);
}
@@ -289,15 +197,13 @@ client_main(int argc, char **argv, int flags)
/* Print the exit message, if any, and exit. */
if (client_attached) {
if (client_exitreason != CLIENT_EXIT_NONE && !login_shell)
printf("[%s]\n", client_exit_message());
if (client_exitmsg != NULL && !login_shell)
printf("[%s]\n", client_exitmsg);
ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP);
} else if (flags & IDENTIFY_TERMIOS)
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
setblocking(STDIN_FILENO, 1);
}
return (client_exitval);
}
@@ -323,7 +229,16 @@ client_send_identify(int flags)
fatal("dup failed");
imsg_compose(&client_ibuf,
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
client_update_event();
if ((fd = dup(STDOUT_FILENO)) == -1)
fatal("dup failed");
imsg_compose(&client_ibuf,
MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0);
if ((fd = dup(STDERR_FILENO)) == -1)
fatal("dup failed");
imsg_compose(&client_ibuf,
MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0);
}
/* Forward entire environment to server. */
@@ -345,7 +260,6 @@ void
client_write_server(enum msgtype type, void *buf, size_t len)
{
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. */
@@ -383,12 +297,12 @@ client_signal(int sig, unused short events, unused void *data)
} else {
switch (sig) {
case SIGHUP:
client_exitreason = CLIENT_EXIT_LOST_TTY;
client_exitmsg = "lost tty";
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
case SIGTERM:
client_exitreason = CLIENT_EXIT_TERMINATED;
client_exitmsg = "terminated";
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
@@ -440,46 +354,11 @@ client_callback(unused int fd, short events, void *data)
return;
lost_server:
client_exitreason = CLIENT_EXIT_LOST_SERVER;
client_exitmsg = "lost server";
client_exitval = 1;
event_loopexit(NULL);
}
/* Callback for client stdin read events. */
/* ARGSUSED */
void
client_stdin_callback(unused int fd, unused short events, unused void *data1)
{
struct msg_stdin_data data;
data.size = read(STDIN_FILENO, data.data, sizeof data.data);
if (data.size < 0 && (errno == EINTR || errno == EAGAIN))
return;
client_write_server(MSG_STDIN, &data, sizeof data);
if (data.size <= 0)
event_del(&client_stdin);
client_update_event();
}
/* Force write to file descriptor. */
void
client_write(int fd, const char *data, size_t size)
{
ssize_t used;
while (size != 0) {
used = write(fd, data, size);
if (used == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
break;
}
data += used;
size -= used;
}
}
/* Dispatch imsgs when in wait state (before MSG_READY). */
int
client_dispatch_wait(void *data)
@@ -488,10 +367,11 @@ client_dispatch_wait(void *data)
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;
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
fatalx("imsg_read failed");
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
@@ -499,7 +379,6 @@ client_dispatch_wait(void *data)
return (0);
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:
@@ -516,36 +395,14 @@ client_dispatch_wait(void *data)
if (datalen != 0)
fatalx("bad MSG_READY size");
event_del(&client_stdin);
client_attached = 1;
break;
case MSG_STDIN:
if (datalen != 0)
fatalx("bad MSG_STDIN size");
event_add(&client_stdin, NULL);
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
fatalx("bad MSG_STDOUT");
memcpy(&stdoutdata, imsg.data, sizeof stdoutdata);
client_write(STDOUT_FILENO, stdoutdata.data, stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
fatalx("bad MSG_STDERR");
memcpy(&stderrdata, imsg.data, sizeof stderrdata);
client_write(STDERR_FILENO, stderrdata.data, stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
fatalx("bad MSG_VERSION size");
fprintf(stderr, "protocol version mismatch "
"(client %u, server %u)\n", PROTOCOL_VERSION,
imsg.hdr.peerid);
log_warnx("protocol version mismatch (client %u, "
"server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
client_exitval = 1;
imsg_free(&imsg);
@@ -560,12 +417,6 @@ client_dispatch_wait(void *data)
shell_exec(shelldata.shell, shellcmd);
/* NOTREACHED */
case MSG_DETACH:
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
default:
fatalx("unexpected message");
}
@@ -591,7 +442,7 @@ client_dispatch_attached(void)
return (0);
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
log_debug("got %d from server", imsg.hdr.type);
log_debug("client got %d", imsg.hdr.type);
switch (imsg.hdr.type) {
case MSG_DETACHKILL:
case MSG_DETACH:
@@ -600,9 +451,9 @@ client_dispatch_attached(void)
client_exittype = imsg.hdr.type;
if (imsg.hdr.type == MSG_DETACHKILL)
client_exitreason = CLIENT_EXIT_DETACHED_HUP;
client_exitmsg = "detached and SIGHUP";
else
client_exitreason = CLIENT_EXIT_DETACHED;
client_exitmsg = "detached";
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXIT:
@@ -611,7 +462,7 @@ client_dispatch_attached(void)
fatalx("bad MSG_EXIT size");
client_write_server(MSG_EXITING, NULL, 0);
client_exitreason = CLIENT_EXIT_EXITED;
client_exitmsg = "exited";
break;
case MSG_EXITED:
if (datalen != 0)
@@ -624,7 +475,7 @@ client_dispatch_attached(void)
fatalx("bad MSG_SHUTDOWN size");
client_write_server(MSG_EXITING, NULL, 0);
client_exitreason = CLIENT_EXIT_SERVER_EXITED;
client_exitmsg = "server exited";
client_exitval = 1;
break;
case MSG_SUSPEND:

View File

@@ -18,15 +18,13 @@
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Attach existing session to the current terminal.
*/
enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
@@ -38,26 +36,26 @@ const struct cmd_entry cmd_attach_session_entry = {
cmd_attach_session_exec
};
enum cmd_retval
int
cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s;
struct client *c;
const char *update;
char *cause;
char *overrides, *cause;
u_int i;
if (RB_EMPTY(&sessions)) {
ctx->error(ctx, "no sessions");
return (CMD_RETURN_ERROR);
return (-1);
}
if ((s = cmd_find_session(ctx, args_get(args, 't'), 1)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (ctx->cmdclient == NULL && ctx->curclient == NULL)
return (CMD_RETURN_NORMAL);
return (0);
if (ctx->cmdclient == NULL) {
if (args_has(self->args, 'd')) {
@@ -76,15 +74,20 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
}
ctx->curclient->session = s;
notify_attached_session_changed(ctx->curclient);
session_update_activity(s);
server_redraw_client(ctx->curclient);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else {
if (server_client_open(ctx->cmdclient, s, &cause) != 0) {
ctx->error(ctx, "open terminal failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
overrides =
options_get_string(&s->options, "terminal-overrides");
if (tty_open(&ctx->cmdclient->tty, overrides, &cause) != 0) {
ctx->error(ctx, "terminal open failed: %s", cause);
xfree(cause);
return (-1);
}
if (args_has(self->args, 'r'))
@@ -94,18 +97,16 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s;
notify_attached_session_changed(ctx->cmdclient);
session_update_activity(s);
server_write_ready(ctx->cmdclient);
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
update = options_get_string(&s->options, "update-environment");
environ_update(update, &ctx->cmdclient->environ, &s->environ);
server_redraw_client(ctx->cmdclient);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
}
recalculate_sizes();
server_update_socket();
return (CMD_RETURN_ATTACH);
return (1); /* 1 means don't tell command client to exit */
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -27,10 +26,10 @@
* 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_ctx *);
int cmd_bind_key_check(struct args *);
int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_ctx *, int);
int cmd_bind_key_table(struct cmd *, struct cmd_ctx *, int);
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
@@ -42,20 +41,20 @@ const struct cmd_entry cmd_bind_key_entry = {
cmd_bind_key_exec
};
enum cmd_retval
int
cmd_bind_key_check(struct args *args)
{
if (args_has(args, 't')) {
if (args->argc != 2)
return (CMD_RETURN_ERROR);
return (-1);
} else {
if (args->argc < 2)
return (CMD_RETURN_ERROR);
return (-1);
}
return (CMD_RETURN_NORMAL);
return (0);
}
enum cmd_retval
int
cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -66,7 +65,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx)
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
return (-1);
}
if (args_has(args, 't'))
@@ -75,17 +74,17 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx)
cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, &cause);
if (cmdlist == NULL) {
ctx->error(ctx, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
if (!args_has(args, 'n'))
key |= KEYC_PREFIX;
key_bindings_add(key, args_has(args, 'r'), cmdlist);
return (CMD_RETURN_NORMAL);
return (0);
}
enum cmd_retval
int
cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
{
struct args *args = self->args;
@@ -97,25 +96,25 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
tablename = args_get(args, 't');
if ((mtab = mode_key_findtable(tablename)) == NULL) {
ctx->error(ctx, "unknown key table: %s", tablename);
return (CMD_RETURN_ERROR);
return (-1);
}
cmd = mode_key_fromstring(mtab->cmdstr, args->argv[1]);
if (cmd == MODEKEY_NONE) {
ctx->error(ctx, "unknown command: %s", args->argv[1]);
return (CMD_RETURN_ERROR);
return (-1);
}
mtmp.key = key;
mtmp.mode = !!args_has(args, 'c');
if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
mbind->cmd = cmd;
return (CMD_RETURN_NORMAL);
return (0);
}
mbind = xmalloc(sizeof *mbind);
mbind->key = mtmp.key;
mbind->mode = mtmp.mode;
mbind->cmd = cmd;
RB_INSERT(mode_key_tree, mtab->tree, mbind);
return (CMD_RETURN_NORMAL);
SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
return (0);
}

View File

@@ -26,19 +26,19 @@
* Break pane off into a window.
*/
enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp",
"dPF:t:", 0, 0,
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
"dt:", 0, 0,
"[-d] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_break_pane_exec
};
enum cmd_retval
int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -46,20 +46,15 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
struct window_pane *wp;
struct window *w;
char *name;
char *cause;
int base_idx;
struct client *c;
struct format_tree *ft;
const char *template;
char *cp;
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't break with only one pane");
return (CMD_RETURN_ERROR);
return (-1);
}
w = wl->window;
@@ -79,9 +74,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
w = wp->window = window_create1(s->sx, s->sy);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
name = default_window_name(w);
window_set_name(w, name);
free(name);
w->name = default_window_name(w);
layout_init(w);
base_idx = options_get_number(&s->options, "base-index");
@@ -92,23 +85,5 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_session(s);
server_status_session_group(s);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = BREAK_PANE_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(ctx, NULL)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
cp = format_expand(ft, template);
ctx->print(ctx, "%s", cp);
free(cp);
format_free(ft);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,7 +27,7 @@
* Write the entire contents of a pane to a buffer.
*/
enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *);
int cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep",
@@ -39,7 +39,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
cmd_capture_pane_exec
};
enum cmd_retval
int
cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -52,17 +52,17 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
size_t len, linelen;
if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
s = &wp->base;
gd = s->grid;
buf = NULL;
len = 0;
n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
n = args_strtonum(args, 'S', SHRT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
top = gd->hsize;
free(cause);
xfree(cause);
} else if (n < 0 && (u_int) -n > gd->hsize)
top = 0;
else
@@ -70,10 +70,10 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (top > gd->hsize + gd->sy - 1)
top = gd->hsize + gd->sy - 1;
n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
n = args_strtonum(args, 'E', SHRT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
free(cause);
xfree(cause);
} else if (n < 0 && (u_int) -n > gd->hsize)
bottom = 0;
else
@@ -96,29 +96,28 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
len += linelen;
buf[len++] = '\n';
free(line);
xfree(line);
}
limit = options_get_number(&global_options, "buffer-limit");
if (!args_has(args, 'b')) {
paste_add(&global_buffers, buf, len, limit);
return (CMD_RETURN_NORMAL);
return (0);
}
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(buf);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
if (paste_replace(&global_buffers, buffer, buf, len) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
free(buf);
return (CMD_RETURN_ERROR);
xfree(buf);
return (-1);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include "tmux.h"
@@ -27,100 +26,118 @@
* Enter choice mode to choose a buffer.
*/
enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *);
int cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_buffer_callback(struct window_choose_data *);
void cmd_choose_buffer_free(struct window_choose_data *);
void cmd_choose_buffer_callback(void *, int);
void cmd_choose_buffer_free(void *);
const struct cmd_entry cmd_choose_buffer_entry = {
"choose-buffer", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]",
0,
NULL,
NULL,
cmd_choose_buffer_exec
};
enum cmd_retval
struct cmd_choose_buffer_data {
struct client *client;
char *template;
};
int
cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct window_choose_data *cdata;
struct cmd_choose_buffer_data *cdata;
struct winlink *wl;
struct paste_buffer *pb;
char *action, *action_data;
const char *template;
u_int idx;
char *tmp;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
return (-1);
}
if ((template = args_get(args, 'F')) == NULL)
template = CHOOSE_BUFFER_TEMPLATE;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (paste_get_top(&global_buffers) == NULL)
return (CMD_RETURN_NORMAL);
return (0);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
if (args->argc != 0)
action = xstrdup(args->argv[0]);
else
action = xstrdup("paste-buffer -b '%%'");
return (0);
idx = 0;
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
cdata = window_choose_data_create(ctx);
cdata->idx = idx - 1;
cdata->client->references++;
cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", idx - 1);
format_paste_buffer(cdata->ft, pb);
xasprintf(&action_data, "%u", idx - 1);
cdata->command = cmd_template_replace(action, action_data, 1);
free(action_data);
window_choose_add(wl->window->active, cdata);
tmp = paste_print(pb, 50);
window_choose_add(wl->window->active, idx - 1,
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
xfree(tmp);
}
free(action);
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
cdata->template = xstrdup("paste-buffer -b '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready(wl->window->active,
0, cmd_choose_buffer_callback, cmd_choose_buffer_free);
0, cmd_choose_buffer_callback, cmd_choose_buffer_free, cdata);
return (CMD_RETURN_NORMAL);
return (0);
}
void
cmd_choose_buffer_callback(struct window_choose_data *cdata)
cmd_choose_buffer_callback(void *data, int idx)
{
if (cdata == NULL)
struct cmd_choose_buffer_data *cdata = data;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause, tmp[16];
if (idx == -1)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
window_choose_ctx(cdata);
xsnprintf(tmp, sizeof tmp, "%u", idx);
template = cmd_template_replace(cdata->template, tmp, 1);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
xfree(cause);
}
xfree(template);
return;
}
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_buffer_free(struct window_choose_data *data)
cmd_choose_buffer_free(void *data)
{
struct window_choose_data *cdata = data;
if (cdata == NULL)
return;
struct cmd_choose_buffer_data *cdata = data;
cdata->client->references--;
free(cdata->command);
free(cdata->ft_template);
free(cdata);
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include "tmux.h"
@@ -27,15 +26,15 @@
* Enter choice mode to choose a client.
*/
enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_ctx *);
int cmd_choose_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_client_callback(struct window_choose_data *);
void cmd_choose_client_free(struct window_choose_data *);
void cmd_choose_client_callback(void *, int);
void cmd_choose_client_free(void *);
const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]",
0,
NULL,
NULL,
@@ -47,35 +46,25 @@ struct cmd_choose_client_data {
char *template;
};
enum cmd_retval
int
cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct window_choose_data *cdata;
struct cmd_choose_client_data *cdata;
struct winlink *wl;
struct client *c;
const char *template;
char *action;
u_int i, idx, cur;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
return (-1);
}
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
if ((template = args_get(args, 'F')) == NULL)
template = CHOOSE_CLIENT_TEMPLATE;
if (args->argc != 0)
action = xstrdup(args->argv[0]);
else
action = xstrdup("detach-client -t '%%'");
return (0);
cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@@ -86,56 +75,77 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
cur = idx;
idx++;
cdata = window_choose_data_create(ctx);
cdata->idx = i;
cdata->client->references++;
cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", i);
format_session(cdata->ft, c->session);
format_client(cdata->ft, c);
cdata->command = cmd_template_replace(action, c->tty.path, 1);
window_choose_add(wl->window->active, cdata);
window_choose_add(wl->window->active, i,
"%s: %s [%ux%u %s]%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, c->tty.flags & TTY_UTF8 ? " (utf8)" : "");
}
free(action);
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
cdata->template = xstrdup("detach-client -t '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready(wl->window->active,
cur, cmd_choose_client_callback, cmd_choose_client_free);
cur, cmd_choose_client_callback, cmd_choose_client_free, cdata);
return (CMD_RETURN_NORMAL);
return (0);
}
void
cmd_choose_client_callback(struct window_choose_data *cdata)
cmd_choose_client_callback(void *data, int idx)
{
struct client *c;
struct cmd_choose_client_data *cdata = data;
struct client *c;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause;
if (cdata == NULL)
if (idx == -1)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
if (cdata->idx > ARRAY_LENGTH(&clients) - 1)
if ((u_int) idx > ARRAY_LENGTH(&clients) - 1)
return;
c = ARRAY_ITEM(&clients, cdata->idx);
c = ARRAY_ITEM(&clients, idx);
if (c == NULL || c->session == NULL)
return;
template = cmd_template_replace(cdata->template, c->tty.path, 1);
window_choose_ctx(cdata);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause);
xfree(cause);
}
xfree(template);
return;
}
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_client_free(struct window_choose_data *cdata)
cmd_choose_client_free(void *data)
{
if (cdata == NULL)
return;
struct cmd_choose_client_data *cdata = data;
cdata->client->references--;
free(cdata->ft_template);
free(cdata->command);
format_free(cdata->ft);
free(cdata);
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -1,123 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
*
* 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 <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
#define CMD_CHOOSE_LIST_DEFAULT_TEMPLATE "run-shell '%%'"
/*
* Enter choose mode to choose a custom list.
*/
enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_list_callback(struct window_choose_data *);
void cmd_choose_list_free(struct window_choose_data *);
const struct cmd_entry cmd_choose_list_entry = {
"choose-list", NULL,
"l:t:", 0, 1,
"[-l items] " CMD_TARGET_WINDOW_USAGE "[template]",
0,
NULL,
NULL,
cmd_choose_list_exec
};
enum cmd_retval
cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct winlink *wl;
const char *list1;
char *template, *item, *copy, *list;
u_int idx;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
}
if ((list1 = args_get(args, 'l')) == NULL)
return (CMD_RETURN_ERROR);
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
if (args->argc != 0)
template = xstrdup(args->argv[0]);
else
template = xstrdup(CMD_CHOOSE_LIST_DEFAULT_TEMPLATE);
copy = list = xstrdup(list1);
idx = 0;
while ((item = strsep(&list, ",")) != NULL)
{
if (*item == '\0') /* no empty entries */
continue;
window_choose_add_item(wl->window->active, ctx, wl, item,
template, idx);
idx++;
}
free(copy);
if (idx == 0) {
free(template);
window_pane_reset_mode(wl->window->active);
return (CMD_RETURN_ERROR);
}
window_choose_ready(wl->window->active, 0, cmd_choose_list_callback,
cmd_choose_list_free);
free(template);
return (CMD_RETURN_NORMAL);
}
void
cmd_choose_list_callback(struct window_choose_data *cdata)
{
if (cdata == NULL || (cdata->client->flags & CLIENT_DEAD))
return;
window_choose_ctx(cdata);
}
void
cmd_choose_list_free(struct window_choose_data *cdata)
{
cdata->session->references--;
cdata->client->references--;
free(cdata->ft_template);
free(cdata->command);
format_free(cdata->ft);
free(cdata);
}

156
cmd-choose-session.c Normal file
View File

@@ -0,0 +1,156 @@
/* $Id$ */
/*
* Copyright (c) 2009 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 <ctype.h>
#include "tmux.h"
/*
* Enter choice mode to choose a session.
*/
int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_session_callback(void *, int);
void cmd_choose_session_free(void *);
const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL,
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]",
0,
NULL,
NULL,
cmd_choose_session_exec
};
struct cmd_choose_session_data {
struct client *client;
char *template;
};
int
cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct cmd_choose_session_data *cdata;
struct winlink *wl;
struct session *s;
struct session_group *sg;
u_int idx, sgidx, cur;
char tmp[64];
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
cur = idx = 0;
RB_FOREACH(s, sessions, &sessions) {
if (s == ctx->curclient->session)
cur = idx;
idx++;
sg = session_group_find(s);
if (sg == NULL)
*tmp = '\0';
else {
sgidx = session_group_index(sg);
xsnprintf(tmp, sizeof tmp, " (group %u)", sgidx);
}
window_choose_add(wl->window->active, s->idx,
"%s: %u windows [%ux%u]%s%s", s->name,
winlink_count(&s->windows), s->sx, s->sy,
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
}
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
cdata->template = xstrdup("switch-client -t '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready(wl->window->active,
cur, cmd_choose_session_callback, cmd_choose_session_free, cdata);
return (0);
}
void
cmd_choose_session_callback(void *data, int idx)
{
struct cmd_choose_session_data *cdata = data;
struct session *s;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause;
if (idx == -1)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
s = session_find_by_index(idx);
if (s == NULL)
return;
template = cmd_template_replace(cdata->template, s->name, 1);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
xfree(cause);
}
xfree(template);
return;
}
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_session_free(void *data)
{
struct cmd_choose_session_data *cdata = data;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -1,261 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
*
* 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 <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
#define CMD_CHOOSE_TREE_WINDOW_ACTION "select-window -t '%%'"
#define CMD_CHOOSE_TREE_SESSION_ACTION "switch-client -t '%%'"
/*
* Enter choice mode to choose a session and/or window.
*/
enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_tree_callback(struct window_choose_data *);
void cmd_choose_tree_free(struct window_choose_data *);
const struct cmd_entry cmd_choose_tree_entry = {
"choose-tree", NULL,
"S:W:swb:c:t:", 0, 1,
"[-sw] [-b session-template] [-c window template] [-S format] " \
"[-W format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_choose_tree_exec
};
const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_tree_exec
};
const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
0,
NULL,
NULL,
cmd_choose_tree_exec
};
enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct winlink *wl, *wm;
struct session *s, *s2;
struct window_choose_data *wcd = NULL;
const char *ses_template, *win_template;
char *final_win_action, *cur_win_template;
char *final_win_template_middle;
char *final_win_template_last;
const char *ses_action, *win_action;
u_int cur_win, idx_ses, win_ses, win_max;
u_int wflag, sflag;
ses_template = win_template = NULL;
ses_action = win_action = NULL;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
}
s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
/* Sort out which command this is. */
wflag = sflag = 0;
if (self->entry == &cmd_choose_session_entry) {
sflag = 1;
if ((ses_template = args_get(args, 'F')) == NULL)
ses_template = CHOOSE_TREE_SESSION_TEMPLATE;
if (args->argc != 0)
ses_action = args->argv[0];
else
ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
} else if (self->entry == &cmd_choose_window_entry) {
wflag = 1;
if ((win_template = args_get(args, 'F')) == NULL)
win_template = CHOOSE_TREE_WINDOW_TEMPLATE;
if (args->argc != 0)
win_action = args->argv[0];
else
win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
} else {
wflag = args_has(args, 'w');
sflag = args_has(args, 's');
if ((ses_action = args_get(args, 'b')) == NULL)
ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
if ((win_action = args_get(args, 'c')) == NULL)
win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
if ((ses_template = args_get(args, 'S')) == NULL)
ses_template = CHOOSE_TREE_SESSION_TEMPLATE;
if ((win_template = args_get(args, 'W')) == NULL)
win_template = CHOOSE_TREE_WINDOW_TEMPLATE;
}
/*
* If not asking for windows and sessions, assume no "-ws" given and
* hence display the entire tree outright.
*/
if (!wflag && !sflag)
wflag = sflag = 1;
/*
* If we're drawing in tree mode, including sessions, then pad the
* window template, otherwise just render the windows as a flat list
* without any padding.
*/
if (wflag && sflag) {
xasprintf(&final_win_template_middle,
" \001tq\001> %s", win_template);
xasprintf(&final_win_template_last,
" \001mq\001> %s", win_template);
} else if (wflag) {
final_win_template_middle = xstrdup(win_template);
final_win_template_last = xstrdup(win_template);
} else
final_win_template_middle = final_win_template_last = NULL;
idx_ses = cur_win = -1;
RB_FOREACH(s2, sessions, &sessions) {
idx_ses++;
/*
* If we're just choosing windows, jump straight there. Note
* that this implies the current session, so only choose
* windows when the session matches this one.
*/
if (wflag && !sflag) {
if (s != s2)
continue;
goto windows_only;
}
wcd = window_choose_add_session(wl->window->active,
ctx, s2, ses_template, (char *)ses_action, idx_ses);
/* If we're just choosing sessions, skip choosing windows. */
if (sflag && !wflag) {
if (s == s2)
cur_win = idx_ses;
continue;
}
windows_only:
win_ses = win_max = -1;
RB_FOREACH(wm, winlinks, &s2->windows)
win_max++;
RB_FOREACH(wm, winlinks, &s2->windows) {
win_ses++;
if (sflag && wflag)
idx_ses++;
if (wm == s2->curw && s == s2) {
if (wflag && !sflag) {
/*
* Then we're only counting windows.
* So remember which is the current
* window in the list.
*/
cur_win = win_ses;
} else
cur_win = idx_ses;
}
xasprintf(&final_win_action, "%s ; %s", win_action,
wcd ? wcd->command : "");
if (win_ses != win_max)
cur_win_template = final_win_template_middle;
else
cur_win_template = final_win_template_last;
window_choose_add_window(wl->window->active,
ctx, s2, wm, cur_win_template,
final_win_action,
(wflag && !sflag) ? win_ses : idx_ses);
free(final_win_action);
}
/*
* If we're just drawing windows, don't consider moving on to
* other sessions as we only list windows in this session.
*/
if (wflag && !sflag)
break;
}
free(final_win_template_middle);
free(final_win_template_last);
window_choose_ready(wl->window->active, cur_win,
cmd_choose_tree_callback, cmd_choose_tree_free);
return (CMD_RETURN_NORMAL);
}
void
cmd_choose_tree_callback(struct window_choose_data *cdata)
{
if (cdata == NULL)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
window_choose_ctx(cdata);
}
void
cmd_choose_tree_free(struct window_choose_data *cdata)
{
cdata->session->references--;
cdata->client->references--;
free(cdata->ft_template);
free(cdata->command);
format_free(cdata->ft);
free(cdata);
}

169
cmd-choose-window.c Normal file
View File

@@ -0,0 +1,169 @@
/* $Id$ */
/*
* Copyright (c) 2009 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 <ctype.h>
#include "tmux.h"
/*
* Enter choice mode to choose a window.
*/
int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_window_callback(void *, int);
void cmd_choose_window_free(void *);
const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL,
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]",
0,
NULL,
NULL,
cmd_choose_window_exec
};
struct cmd_choose_window_data {
struct client *client;
struct session *session;
char *template;
};
int
cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct cmd_choose_window_data *cdata;
struct session *s;
struct winlink *wl, *wm;
struct window *w;
u_int idx, cur;
char *flags, *title;
const char *left, *right;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
cur = idx = 0;
RB_FOREACH(wm, winlinks, &s->windows) {
w = wm->window;
if (wm == s->curw)
cur = idx;
idx++;
flags = window_printable_flags(s, wm);
title = w->active->screen->title;
if (wm == wl)
title = w->active->base.title;
left = " \"";
right = "\"";
if (*title == '\0')
left = right = "";
window_choose_add(wl->window->active,
wm->idx, "%3d: %s%s [%ux%u] (%u panes%s)%s%s%s",
wm->idx, w->name, flags, w->sx, w->sy, window_count_panes(w),
w->active->fd == -1 ? ", dead" : "",
left, title, right);
xfree(flags);
}
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
cdata->template = xstrdup("select-window -t '%%'");
cdata->session = s;
cdata->session->references++;
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready(wl->window->active,
cur, cmd_choose_window_callback, cmd_choose_window_free, cdata);
return (0);
}
void
cmd_choose_window_callback(void *data, int idx)
{
struct cmd_choose_window_data *cdata = data;
struct session *s = cdata->session;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *target, *template, *cause;
if (idx == -1)
return;
if (!session_alive(s))
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
xasprintf(&target, "%s:%d", s->name, idx);
template = cmd_template_replace(cdata->template, target, 1);
xfree(target);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
xfree(cause);
}
xfree(template);
return;
}
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_window_free(void *data)
{
struct cmd_choose_window_data *cdata = data;
cdata->session->references--;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -24,7 +24,7 @@
* Clear pane history.
*/
enum cmd_retval cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist",
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_clear_history_entry = {
cmd_clear_history_exec
};
enum cmd_retval
int
cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -44,11 +44,11 @@ cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
struct grid *gd;
if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
gd = wp->base.grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy);
gd->hsize = 0;
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,7 +24,7 @@
* Enter clock mode.
*/
enum cmd_retval cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *);
int cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL,
@@ -36,16 +36,16 @@ const struct cmd_entry cmd_clock_mode_entry = {
cmd_clock_mode_exec
};
enum cmd_retval
int
cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct window_pane *wp;
if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
window_pane_set_mode(wp, &window_clock_mode);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -31,7 +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_ctx *);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_free(void *);
@@ -84,7 +83,7 @@ cmd_command_prompt_key_binding(struct cmd *self, int key)
}
}
enum cmd_retval
int
cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -95,10 +94,10 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
size_t n;
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (c->prompt_string != NULL)
return (CMD_RETURN_NORMAL);
return (0);
cdata = xmalloc(sizeof *cdata);
cdata->c = c;
@@ -139,9 +138,9 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, 0);
free(prompt);
xfree(prompt);
return (CMD_RETURN_NORMAL);
return (0);
}
int
@@ -158,7 +157,7 @@ cmd_command_prompt_callback(void *data, const char *s)
return (0);
new_template = cmd_template_replace(cdata->template, s, cdata->idx);
free(cdata->template);
xfree(cdata->template);
cdata->template = new_template;
/*
@@ -170,7 +169,7 @@ cmd_command_prompt_callback(void *data, const char *s)
input = strsep(&cdata->next_input, ",");
status_prompt_update(c, prompt, input);
free(prompt);
xfree(prompt);
cdata->idx++;
return (1);
}
@@ -179,7 +178,7 @@ cmd_command_prompt_callback(void *data, const char *s)
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause);
free(cause);
xfree(cause);
}
return (0);
}
@@ -206,8 +205,11 @@ cmd_command_prompt_free(void *data)
{
struct cmd_command_prompt_cdata *cdata = data;
free(cdata->inputs);
free(cdata->prompts);
free(cdata->template);
free(cdata);
if (cdata->inputs != NULL)
xfree(cdata->inputs);
if (cdata->prompts != NULL)
xfree(cdata->prompts);
if (cdata->template != NULL)
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -17,7 +17,6 @@
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -26,11 +25,11 @@
* Asks for confirmation before executing a command.
*/
void cmd_confirm_before_key_binding(struct cmd *, int);
enum cmd_retval cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *);
void cmd_confirm_before_key_binding(struct cmd *, int);
int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *);
int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *);
int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *);
const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm",
@@ -65,7 +64,7 @@ cmd_confirm_before_key_binding(struct cmd *self, int key)
}
}
enum cmd_retval
int
cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -76,11 +75,11 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
return (-1);
}
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if ((prompt = args_get(args, 'p')) != NULL)
xasprintf(&new_prompt, "%s ", prompt);
@@ -88,7 +87,7 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
ptr = copy = xstrdup(args->argv[0]);
cmd = strsep(&ptr, " \t");
xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd);
free(copy);
xfree(copy);
}
cdata = xmalloc(sizeof *cdata);
@@ -98,8 +97,8 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE);
free(new_prompt);
return (CMD_RETURN_YIELD);
xfree(new_prompt);
return (1);
}
int
@@ -120,7 +119,7 @@ cmd_confirm_before_callback(void *data, const char *s)
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause);
free(cause);
xfree(cause);
}
return (0);
}
@@ -145,6 +144,7 @@ cmd_confirm_before_free(void *data)
{
struct cmd_confirm_before_data *cdata = data;
free(cdata->cmd);
free(cdata);
if (cdata->cmd != NULL)
xfree(cdata->cmd);
xfree(cdata);
}

View File

@@ -24,8 +24,8 @@
* Enter copy mode.
*/
void cmd_copy_mode_key_binding(struct cmd *, int);
enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_mode_key_binding(struct cmd *, int);
int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL,
@@ -45,20 +45,20 @@ cmd_copy_mode_key_binding(struct cmd *self, int key)
args_set(self->args, 'u', NULL);
}
enum cmd_retval
int
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct window_pane *wp;
if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
return (CMD_RETURN_NORMAL);
return (0);
window_copy_init_from_pane(wp);
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
window_copy_pageup(wp);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,7 +26,7 @@
* Delete a paste buffer.
*/
enum cmd_retval cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb",
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_delete_buffer_entry = {
cmd_delete_buffer_exec
};
enum cmd_retval
int
cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -47,20 +47,20 @@ cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if (!args_has(args, 'b')) {
paste_free_top(&global_buffers);
return (CMD_RETURN_NORMAL);
return (0);
}
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
if (paste_free_index(&global_buffers, buffer) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
return (CMD_RETURN_ERROR);
return (-1);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,23 +24,23 @@
* Detach a client.
*/
enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach",
"as:t:P", 0, 0,
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
"s:t:P", 0, 0,
"[-P] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
CMD_READONLY,
NULL,
NULL,
cmd_detach_client_exec
};
enum cmd_retval
int
cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c, *c2;
struct client *c;
struct session *s;
enum msgtype msgtype;
u_int i;
@@ -53,7 +53,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(args, 's')) {
s = cmd_find_session(ctx, args_get(args, 's'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
return (-1);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
@@ -63,18 +63,10 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
} else {
c = cmd_find_client(ctx, args_get(args, 't'));
if (c == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (args_has(args, 'a')) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c2 = ARRAY_ITEM(&clients, i);
if (c2 == NULL || c == c2)
continue;
server_write_client(c2, msgtype, NULL, 0);
}
} else
server_write_client(c, msgtype, NULL, 0);
server_write_client(c, msgtype, NULL, 0);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include "tmux.h"
@@ -27,19 +26,19 @@
* Displays a message in the status line.
*/
enum cmd_retval cmd_display_message_exec(struct cmd *, struct cmd_ctx *);
int cmd_display_message_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_message_entry = {
"display-message", "display",
"c:pt:F:", 0, 1,
"[-p] [-c target-client] [-t target-pane] [-F format] [message]",
"c:pt:", 0, 1,
"[-p] [-c target-client] [-t target-pane] [message]",
0,
NULL,
NULL,
cmd_display_message_exec
};
enum cmd_retval
int
cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -49,52 +48,31 @@ cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window_pane *wp;
const char *template;
char *msg;
struct format_tree *ft;
char out[BUFSIZ];
time_t t;
size_t len;
if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (args_has(args, 't')) {
if (args_has(args, 't') != 0) {
wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
} else {
wl = cmd_find_pane(ctx, NULL, &s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
s = NULL;
wl = NULL;
wp = NULL;
}
if (args_has(args, 'F') && args->argc != 0) {
ctx->error(ctx, "only one of -F or argument must be given");
return (CMD_RETURN_ERROR);
}
template = args_get(args, 'F');
if (args->argc != 0)
if (args->argc == 0)
template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)";
else
template = args->argv[0];
if (template == NULL)
template = DISPLAY_MESSAGE_TEMPLATE;
ft = format_create();
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
t = time(NULL);
len = strftime(out, sizeof out, template, localtime(&t));
out[len] = '\0';
msg = format_expand(ft, out);
msg = status_replace(c, s, wl, wp, template, time(NULL), 0);
if (args_has(self->args, 'p'))
ctx->print(ctx, "%s", msg);
else
status_message_set(c, "%s", msg);
xfree(msg);
free(msg);
format_free(ft);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,7 +24,7 @@
* Display panes on a client.
*/
enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_ctx *);
int cmd_display_panes_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp",
@@ -36,16 +36,16 @@ const struct cmd_entry cmd_display_panes_entry = {
cmd_display_panes_exec
};
enum cmd_retval
int
cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c;
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
server_set_identify(c);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <fnmatch.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -28,25 +27,15 @@
* Find window containing text.
*/
enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_find_window_callback(struct window_choose_data *);
void cmd_find_window_free(struct window_choose_data *);
/* Flags for determining matching behavior. */
#define CMD_FIND_WINDOW_BY_TITLE 0x1
#define CMD_FIND_WINDOW_BY_CONTENT 0x2
#define CMD_FIND_WINDOW_BY_NAME 0x4
#define CMD_FIND_WINDOW_ALL \
(CMD_FIND_WINDOW_BY_TITLE | \
CMD_FIND_WINDOW_BY_CONTENT | \
CMD_FIND_WINDOW_BY_NAME)
void cmd_find_window_callback(void *, int);
void cmd_find_window_free(void *);
const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw",
"F:CNt:T", 1, 4,
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
"t:", 1, 1,
CMD_TARGET_WINDOW_USAGE " match-string",
0,
NULL,
NULL,
@@ -54,121 +43,78 @@ const struct cmd_entry cmd_find_window_entry = {
};
struct cmd_find_window_data {
struct winlink *wl;
char *list_ctx;
u_int pane_id;
struct session *session;
};
ARRAY_DECL(cmd_find_window_data_list, struct cmd_find_window_data);
u_int cmd_find_window_match_flags(struct args *);
void cmd_find_window_match(struct cmd_find_window_data_list *, int,
struct winlink *, const char *, const char *);
u_int
cmd_find_window_match_flags(struct args *args)
{
u_int match_flags = 0;
/* Turn on flags based on the options. */
if (args_has(args, 'T'))
match_flags |= CMD_FIND_WINDOW_BY_TITLE;
if (args_has(args, 'C'))
match_flags |= CMD_FIND_WINDOW_BY_CONTENT;
if (args_has(args, 'N'))
match_flags |= CMD_FIND_WINDOW_BY_NAME;
/* If none of the flags were set, default to matching anything. */
if (match_flags == 0)
match_flags = CMD_FIND_WINDOW_ALL;
return (match_flags);
}
void
cmd_find_window_match(struct cmd_find_window_data_list *find_list,
int match_flags, struct winlink *wl, const char *str, const char *searchstr)
{
struct cmd_find_window_data find_data;
struct window_pane *wp;
u_int i, line;
char *sres;
memset(&find_data, 0, sizeof find_data);
i = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
i++;
if ((match_flags & CMD_FIND_WINDOW_BY_NAME) &&
fnmatch(searchstr, wl->window->name, 0) == 0) {
find_data.list_ctx = xstrdup("");
break;
}
if ((match_flags & CMD_FIND_WINDOW_BY_TITLE) &&
fnmatch(searchstr, wp->base.title, 0) == 0) {
xasprintf(&find_data.list_ctx,
"pane %u title: \"%s\"", i - 1, wp->base.title);
break;
}
if (match_flags & CMD_FIND_WINDOW_BY_CONTENT &&
(sres = window_pane_search(wp, str, &line)) != NULL) {
xasprintf(&find_data.list_ctx,
"pane %u line %u: \"%s\"", i - 1, line + 1, sres);
free(sres);
break;
}
}
if (find_data.list_ctx != NULL) {
find_data.wl = wl;
find_data.pane_id = i - 1;
ARRAY_ADD(find_list, find_data);
}
}
enum cmd_retval
int
cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct window_choose_data *cdata;
struct cmd_find_window_data *cdata;
struct session *s;
struct winlink *wl, *wm;
struct cmd_find_window_data_list find_list;
char *str, *searchstr;
const char *template;
u_int i, match_flags;
struct window *w;
struct window_pane *wp;
ARRAY_DECL(, u_int) list_idx;
ARRAY_DECL(, char *) list_ctx;
char *str, *sres, *sctx, *searchstr;
u_int i, line;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (CMD_RETURN_ERROR);
return (-1);
}
s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if ((template = args_get(args, 'F')) == NULL)
template = FIND_WINDOW_TEMPLATE;
match_flags = cmd_find_window_match_flags(args);
str = args->argv[0];
ARRAY_INIT(&find_list);
ARRAY_INIT(&list_idx);
ARRAY_INIT(&list_ctx);
xasprintf(&searchstr, "*%s*", str);
RB_FOREACH(wm, winlinks, &s->windows)
cmd_find_window_match (&find_list, match_flags, wm, str, searchstr);
free(searchstr);
RB_FOREACH(wm, winlinks, &s->windows) {
i = 0;
TAILQ_FOREACH(wp, &wm->window->panes, entry) {
i++;
if (ARRAY_LENGTH(&find_list) == 0) {
if (fnmatch(searchstr, wm->window->name, 0) == 0)
sctx = xstrdup("");
else {
sres = window_pane_search(wp, str, &line);
if (sres == NULL &&
fnmatch(searchstr, wp->base.title, 0) != 0)
continue;
if (sres == NULL) {
xasprintf(&sctx,
"pane %u title: \"%s\"", i - 1,
wp->base.title);
} else {
xasprintf(&sctx,
"pane %u line %u: \"%s\"", i - 1,
line + 1, sres);
xfree(sres);
}
}
ARRAY_ADD(&list_idx, wm->idx);
ARRAY_ADD(&list_ctx, sctx);
}
}
xfree(searchstr);
if (ARRAY_LENGTH(&list_idx) == 0) {
ctx->error(ctx, "no windows matching: %s", str);
ARRAY_FREE(&find_list);
return (CMD_RETURN_ERROR);
ARRAY_FREE(&list_idx);
ARRAY_FREE(&list_ctx);
return (-1);
}
if (ARRAY_LENGTH(&find_list) == 1) {
if (session_select(s, ARRAY_FIRST(&find_list).wl->idx) == 0)
if (ARRAY_LENGTH(&list_idx) == 1) {
if (session_select(s, ARRAY_FIRST(&list_idx)) == 0)
server_redraw_session(s);
recalculate_sizes();
goto out;
@@ -177,66 +123,54 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
goto out;
for (i = 0; i < ARRAY_LENGTH(&find_list); i++) {
wm = ARRAY_ITEM(&find_list, i).wl;
for (i = 0; i < ARRAY_LENGTH(&list_idx); i++) {
wm = winlink_find_by_index(
&s->windows, ARRAY_ITEM(&list_idx, i));
w = wm->window;
cdata = window_choose_data_create(ctx);
cdata->idx = wm->idx;
cdata->client->references++;
cdata->wl = wm;
cdata->ft_template = xstrdup(template);
cdata->pane_id = ARRAY_ITEM(&find_list, i).pane_id;
format_add(cdata->ft, "line", "%u", i);
format_add(cdata->ft, "window_find_matches", "%s",
ARRAY_ITEM(&find_list, i).list_ctx);
format_session(cdata->ft, s);
format_winlink(cdata->ft, s, wm);
window_choose_add(wl->window->active, cdata);
sctx = ARRAY_ITEM(&list_ctx, i);
window_choose_add(wl->window->active,
wm->idx, "%3d: %s [%ux%u] (%u panes) %s", wm->idx, w->name,
w->sx, w->sy, window_count_panes(w), sctx);
xfree(sctx);
}
cdata = xmalloc(sizeof *cdata);
cdata->session = s;
cdata->session->references++;
window_choose_ready(wl->window->active,
0, cmd_find_window_callback, cmd_find_window_free);
0, cmd_find_window_callback, cmd_find_window_free, cdata);
out:
ARRAY_FREE(&find_list);
return (CMD_RETURN_NORMAL);
ARRAY_FREE(&list_idx);
ARRAY_FREE(&list_ctx);
return (0);
}
void
cmd_find_window_callback(struct window_choose_data *cdata)
cmd_find_window_callback(void *data, int idx)
{
struct session *s;
struct window_pane *wp;
struct cmd_find_window_data *cdata = data;
struct session *s = cdata->session;
if (cdata == NULL)
if (idx == -1)
return;
s = cdata->session;
if (!session_alive(s))
return;
wp = window_pane_at_index(cdata->wl->window, cdata->pane_id);
if (wp != NULL && window_pane_visible(wp))
window_set_active_pane(cdata->wl->window, wp);
if (session_select(s, cdata->idx) == 0) {
if (session_select(s, idx) == 0) {
server_redraw_session(s);
recalculate_sizes();
}
}
void
cmd_find_window_free(struct window_choose_data *cdata)
cmd_find_window_free(void *data)
{
if (cdata == NULL)
return;
struct cmd_find_window_data *cdata = data;
cdata->session->references--;
free(cdata->ft_template);
format_free(cdata->ft);
free(cdata);
xfree(cdata);
}

View File

@@ -24,7 +24,7 @@
* Cause client to report an error and exit with 1 if session doesn't exist.
*/
enum cmd_retval cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
int cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_has_session_entry = {
"has-session", "has",
@@ -36,13 +36,13 @@ const struct cmd_entry cmd_has_session_entry = {
cmd_has_session_exec
};
enum cmd_retval
int
cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
if (cmd_find_session(ctx, args_get(args, 't'), 0) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -20,24 +20,23 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Executes a tmux command if a shell command returns true or false.
* Executes a tmux command if a shell command returns true.
*/
enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_if_shell_callback(struct job *);
void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
"", 2, 3,
"shell-command command [command]",
"", 2, 2,
"shell-command command",
0,
NULL,
NULL,
@@ -45,12 +44,11 @@ const struct cmd_entry cmd_if_shell_entry = {
};
struct cmd_if_shell_data {
char *cmd_if;
char *cmd_else;
char *cmd;
struct cmd_ctx ctx;
};
enum cmd_retval
int
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -58,11 +56,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *shellcmd = args->argv[0];
cdata = xmalloc(sizeof *cdata);
cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
cdata->cmd_else = xstrdup(args->argv[2]);
else
cdata->cmd_else = NULL;
cdata->cmd = xstrdup(args->argv[1]);
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
if (ctx->cmdclient != NULL)
@@ -72,7 +66,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata);
return (CMD_RETURN_YIELD); /* don't let client exit */
return (1); /* don't let client exit */
}
void
@@ -81,18 +75,15 @@ cmd_if_shell_callback(struct job *job)
struct cmd_if_shell_data *cdata = job->data;
struct cmd_ctx *ctx = &cdata->ctx;
struct cmd_list *cmdlist;
char *cause, *cmd;
char *cause;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) {
cmd = cdata->cmd_else;
if (cmd == NULL)
return;
} else
cmd = cdata->cmd_if;
if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) {
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
return;
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) {
ctx->error(ctx, "%s", cause);
free(cause);
xfree(cause);
}
return;
}
@@ -106,15 +97,16 @@ cmd_if_shell_free(void *data)
{
struct cmd_if_shell_data *cdata = data;
struct cmd_ctx *ctx = &cdata->ctx;
struct msg_exit_data exitdata;
if (ctx->cmdclient != NULL) {
ctx->cmdclient->references--;
exitdata.retcode = ctx->cmdclient->retcode;
ctx->cmdclient->flags |= CLIENT_EXIT;
}
if (ctx->curclient != NULL)
ctx->curclient->references--;
free(cdata->cmd_else);
free(cdata->cmd_if);
free(cdata);
xfree(cdata->cmd);
xfree(cdata);
}

View File

@@ -1,7 +1,6 @@
/* $Id$ */
/*
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -25,34 +24,22 @@
#include "tmux.h"
/*
* Join or move a pane into another (like split/swap/kill).
* Join a pane into another (like split/swap/kill).
*/
void cmd_join_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmd_ctx *);
enum cmd_retval join_pane(struct cmd *, struct cmd_ctx *, int);
void cmd_join_pane_key_binding(struct cmd *, int);
int cmd_join_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_join_pane_entry = {
"join-pane", "joinp",
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
"dhvp:l:s:t:", 0, 0,
"[-dhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
cmd_join_pane_key_binding,
NULL,
cmd_join_pane_exec
};
const struct cmd_entry cmd_move_pane_entry = {
"move-pane", "movep",
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
NULL,
NULL,
cmd_join_pane_exec
};
void
cmd_join_pane_key_binding(struct cmd *self, int key)
{
@@ -67,14 +54,8 @@ cmd_join_pane_key_binding(struct cmd *self, int key)
}
}
enum cmd_retval
int
cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
return (join_pane(self, ctx, self->entry == &cmd_join_pane_entry));
}
enum cmd_retval
join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
{
struct args *args = self->args;
struct session *dst_s;
@@ -88,22 +69,18 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
dst_wl = cmd_find_pane(ctx, args_get(args, 't'), &dst_s, &dst_wp);
if (dst_wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
dst_w = dst_wl->window;
dst_idx = dst_wl->idx;
src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
src_w = src_wl->window;
if (not_same_window && src_w == dst_w) {
if (src_w == dst_w) {
ctx->error(ctx, "can't join a pane to its own window");
return (CMD_RETURN_ERROR);
}
if (!not_same_window && src_wp == dst_wp) {
ctx->error(ctx, "source and target panes must be different");
return (CMD_RETURN_ERROR);
return (-1);
}
type = LAYOUT_TOPBOTTOM;
@@ -115,25 +92,25 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, 100, &cause);
if (cause != NULL) {
ctx->error(ctx, "percentage %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
if (type == LAYOUT_TOPBOTTOM)
size = (dst_wp->sy * percentage) / 100;
else
size = (dst_wp->sx * percentage) / 100;
}
lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'));
if (lc == NULL) {
if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) {
ctx->error(ctx, "create pane failed: pane too small");
return (CMD_RETURN_ERROR);
return (-1);
}
layout_close_pane(src_wp);
@@ -147,8 +124,6 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
if (window_count_panes(src_w) == 0)
server_kill_window(src_w);
else
notify_window_layout_changed(src_w);
src_wp->window = dst_w;
TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
@@ -166,6 +141,5 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window)
} else
server_status_session(dst_s);
notify_window_layout_changed(dst_w);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,7 +26,7 @@
* Kill pane.
*/
enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp",
@@ -38,29 +38,32 @@ const struct cmd_entry cmd_kill_pane_entry = {
cmd_kill_pane_exec
};
enum cmd_retval
int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct winlink *wl;
struct window_pane *loopwp, *tmpwp, *wp;
struct window_pane *loopwp, *nextwp, *wp;
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (window_count_panes(wl->window) == 1) {
/* Only one pane, kill the window. */
server_kill_window(wl->window);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}
if (args_has(self->args, 'a')) {
TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) {
if (loopwp == wp)
continue;
layout_close_pane(loopwp);
window_remove_pane(wl->window, loopwp);
loopwp = TAILQ_FIRST(&wl->window->panes);
while (loopwp != NULL) {
nextwp = TAILQ_NEXT(loopwp, entry);
if (loopwp != wp) {
layout_close_pane(loopwp);
window_remove_pane(wl->window, loopwp);
}
loopwp = nextwp;
}
} else {
layout_close_pane(wp);
@@ -68,5 +71,5 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
}
server_redraw_window(wl->window);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,7 +27,7 @@
* Kill the server and do nothing else.
*/
enum cmd_retval cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
int cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL,
@@ -40,10 +40,10 @@ const struct cmd_entry cmd_kill_server_entry = {
};
/* ARGSUSED */
enum cmd_retval
int
cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
{
kill(getpid(), SIGTERM);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,37 +27,29 @@
* Note this deliberately has no alias to make it hard to hit by accident.
*/
enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
int cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL,
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_kill_session_exec
};
enum cmd_retval
int
cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s, *s2, *s3;
struct session *s;
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (args_has(args, 'a')) {
RB_FOREACH_SAFE(s2, sessions, &sessions, s3) {
if (s != s2) {
server_destroy_session(s2);
session_destroy(s2);
}
}
} else {
server_destroy_session(s);
session_destroy(s);
}
return (CMD_RETURN_NORMAL);
server_destroy_session(s);
session_destroy(s);
return (0);
}

View File

@@ -24,36 +24,29 @@
* Destroy window.
*/
enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw",
"at:", 0, 0,
"[-a] " CMD_TARGET_WINDOW_USAGE,
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_kill_window_exec
};
enum cmd_retval
int
cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct winlink *wl, *wl2, *wl3;
struct session *s;
struct winlink *wl;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) {
RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
if (wl != wl2)
server_kill_window(wl2->window);
}
} else
server_kill_window(wl->window);
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1);
server_kill_window(wl->window);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,7 +26,7 @@
* Link a window into another session.
*/
enum cmd_retval cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw",
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_link_window_entry = {
cmd_link_window_exec
};
enum cmd_retval
int
cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -48,18 +48,18 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
int idx, kflag, dflag;
if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2)
return (CMD_RETURN_ERROR);
return (-1);
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
ctx->error(ctx, "can't link window: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -27,12 +26,12 @@
* List paste buffers.
*/
enum cmd_retval cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb",
"F:", 0, 0,
"[-F format]",
"", 0, 0,
"",
0,
NULL,
NULL,
@@ -40,31 +39,20 @@ const struct cmd_entry cmd_list_buffers_entry = {
};
/* ARGSUSED */
enum cmd_retval
int
cmd_list_buffers_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct paste_buffer *pb;
struct format_tree *ft;
u_int idx;
char *line;
const char *template;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_BUFFERS_TEMPLATE;
char *tmp;
idx = 0;
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
ft = format_create();
format_add(ft, "line", "%u", idx - 1);
format_paste_buffer(ft, pb);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
free(line);
format_free(ft);
tmp = paste_print(pb, 50);
ctx->print(ctx,
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
xfree(tmp);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -32,55 +31,47 @@ int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc",
"F:t:", 0, 0,
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_list_clients_exec
};
/* ARGSUSED */
enum cmd_retval
int
cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c;
struct session *s;
struct format_tree *ft;
const char *template;
u_int i;
char *line;
struct args *args = self->args;
struct client *c;
struct session *s;
u_int i;
const char *s_utf8;
if (args_has(args, 't')) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
return (-1);
} else
s = NULL;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_CLIENTS_TEMPLATE;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (c->tty.flags & TTY_UTF8)
s_utf8 = " (utf8)";
else
s_utf8 = "";
if (s != NULL && s != c->session)
continue;
ft = format_create();
format_add(ft, "line", "%u", i);
format_session(ft, c->session);
format_client(ft, c);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
free(line);
format_free(ft);
ctx->print(ctx, "%s: %s [%ux%u %s]%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, s_utf8);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,7 +24,7 @@
* List all commands with usages.
*/
enum cmd_retval cmd_list_commands_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_commands_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm",
@@ -37,7 +37,7 @@ const struct cmd_entry cmd_list_commands_entry = {
};
/* ARGSUSED */
enum cmd_retval
int
cmd_list_commands_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
const struct cmd_entry **entryp;
@@ -45,5 +45,5 @@ cmd_list_commands_exec(unused struct cmd *self, struct cmd_ctx *ctx)
for (entryp = cmd_table; *entryp != NULL; entryp++)
ctx->print(ctx, "%s %s", (*entryp)->name, (*entryp)->usage);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,8 +26,9 @@
* List key bindings.
*/
enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_ctx *);
enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_ctx *);
int cmd_list_keys_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_keys_table(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk",
@@ -39,7 +40,7 @@ const struct cmd_entry cmd_list_keys_entry = {
cmd_list_keys_exec
};
enum cmd_retval
int
cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -53,8 +54,9 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
return (cmd_list_keys_table(self, ctx));
width = 0;
*flags = '\0';
RB_FOREACH(bd, key_bindings, &key_bindings) {
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
@@ -71,12 +73,11 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
width = keywidth;
}
RB_FOREACH(bd, key_bindings, &key_bindings) {
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
*flags = '\0';
if (!(bd->key & KEYC_PREFIX)) {
if (bd->can_repeat)
xsnprintf(flags, sizeof flags, "-rn ");
@@ -94,7 +95,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "bind-key %s", tmp);
}
return (CMD_RETURN_NORMAL);
return (0);
}
int
@@ -110,12 +111,12 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
tablename = args_get(args, 't');
if ((mtab = mode_key_findtable(tablename)) == NULL) {
ctx->error(ctx, "unknown key table: %s", tablename);
return (CMD_RETURN_ERROR);
return (-1);
}
width = 0;
any_mode = 0;
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
@@ -128,7 +129,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
width = keywidth;
}
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
@@ -144,5 +145,5 @@ cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
}
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
@@ -27,25 +26,24 @@
* List panes on given window.
*/
enum cmd_retval cmd_list_panes_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_panes_exec(struct cmd *, struct cmd_ctx *);
void cmd_list_panes_server(struct cmd *, struct cmd_ctx *);
void cmd_list_panes_session(
struct cmd *, struct session *, struct cmd_ctx *, int);
void cmd_list_panes_window(struct cmd *,
void cmd_list_panes_server(struct cmd_ctx *);
void cmd_list_panes_session(struct session *, struct cmd_ctx *, int);
void cmd_list_panes_window(
struct session *, struct winlink *, struct cmd_ctx *, int);
const struct cmd_entry cmd_list_panes_entry = {
"list-panes", "lsp",
"asF:t:", 0, 0,
"[-as] [-F format] [-t target]",
"ast:", 0, 0,
"[-as] [-t target]",
0,
NULL,
NULL,
cmd_list_panes_exec
};
enum cmd_retval
int
cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -53,92 +51,87 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl;
if (args_has(args, 'a'))
cmd_list_panes_server(self, ctx);
cmd_list_panes_server(ctx);
else if (args_has(args, 's')) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
cmd_list_panes_session(self, s, ctx, 1);
return (-1);
cmd_list_panes_session(s, ctx, 1);
} else {
wl = cmd_find_window(ctx, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
cmd_list_panes_window(self, s, wl, ctx, 0);
return (-1);
cmd_list_panes_window(s, wl, ctx, 0);
}
return (CMD_RETURN_NORMAL);
return (0);
}
void
cmd_list_panes_server(struct cmd *self, struct cmd_ctx *ctx)
cmd_list_panes_server(struct cmd_ctx *ctx)
{
struct session *s;
RB_FOREACH(s, sessions, &sessions)
cmd_list_panes_session(self, s, ctx, 2);
cmd_list_panes_session(s, ctx, 2);
}
void
cmd_list_panes_session(
struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type)
cmd_list_panes_session(struct session *s, struct cmd_ctx *ctx, int type)
{
struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows)
cmd_list_panes_window(self, s, wl, ctx, type);
cmd_list_panes_window(s, wl, ctx, type);
}
void
cmd_list_panes_window(struct cmd *self,
cmd_list_panes_window(
struct session *s, struct winlink *wl, struct cmd_ctx *ctx, int type)
{
struct args *args = self->args;
struct window_pane *wp;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
template = args_get(args, 'F');
if (template == NULL) {
switch (type) {
case 0:
template = "#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 1:
template = "#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 2:
template = "#{session_name}:#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
}
}
struct grid *gd;
struct grid_line *gl;
u_int i, n;
unsigned long long size;
n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
gd = wp->base.grid;
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
free(line);
size = 0;
for (i = 0; i < gd->hsize; i++) {
gl = &gd->linedata[i];
size += gl->cellsize * sizeof *gl->celldata;
size += gl->utf8size * sizeof *gl->utf8data;
}
size += gd->hsize * sizeof *gd->linedata;
format_free(ft);
switch (type) {
case 0:
ctx->print(ctx,
"%u: [%ux%u] [history %u/%u, %llu bytes] %%%u%s%s",
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
wp->id, wp == wp->window->active ? " (active)" : "",
wp->fd == -1 ? " (dead)" : "");
break;
case 1:
ctx->print(ctx,
"%d.%u: [%ux%u] [history %u/%u, %llu bytes] "
"%%%u%s%s", wl->idx,
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
wp->id, wp == wp->window->active ? " (active)" : "",
wp->fd == -1 ? " (dead)" : "");
break;
case 2:
ctx->print(ctx,
"%s:%d.%u: [%ux%u] [history %u/%u, %llu bytes] "
"%%%u%s%s", s->name, wl->idx,
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size,
wp->id, wp == wp->window->active ? " (active)" : "",
wp->fd == -1 ? " (dead)" : "");
break;
}
n++;
}
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -28,44 +27,45 @@
* List all sessions.
*/
enum cmd_retval cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls",
"F:", 0, 0,
"[-F format]",
"", 0, 0,
"",
0,
NULL,
NULL,
cmd_list_sessions_exec
};
enum cmd_retval
cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx)
/* ARGSUSED */
int
cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
struct session_group *sg;
char *tim, tmp[64];
u_int idx;
time_t t;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_SESSIONS_TEMPLATE;
n = 0;
RB_FOREACH(s, sessions, &sessions) {
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
sg = session_group_find(s);
if (sg == NULL)
*tmp = '\0';
else {
idx = session_group_index(sg);
xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
}
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
free(line);
t = s->creation_time.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
format_free(ft);
n++;
ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s%s",
s->name, winlink_count(&s->windows), tim, s->sx, s->sy,
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
@@ -27,84 +26,67 @@
* List windows on given session.
*/
enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
void cmd_list_windows_server(struct cmd *, struct cmd_ctx *);
void cmd_list_windows_session(
struct cmd *, struct session *, struct cmd_ctx *, int);
void cmd_list_windows_server(struct cmd_ctx *);
void cmd_list_windows_session(struct session *, struct cmd_ctx *, int);
const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw",
"F:at:", 0, 0,
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_list_windows_exec
};
enum cmd_retval
int
cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s;
if (args_has(args, 'a'))
cmd_list_windows_server(self, ctx);
cmd_list_windows_server(ctx);
else {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
cmd_list_windows_session(self, s, ctx, 0);
return (-1);
cmd_list_windows_session(s, ctx, 0);
}
return (CMD_RETURN_NORMAL);
return (0);
}
void
cmd_list_windows_server(struct cmd *self, struct cmd_ctx *ctx)
cmd_list_windows_server(struct cmd_ctx *ctx)
{
struct session *s;
RB_FOREACH(s, sessions, &sessions)
cmd_list_windows_session(self, s, ctx, 1);
cmd_list_windows_session(s, ctx, 1);
}
void
cmd_list_windows_session(
struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type)
cmd_list_windows_session(struct session *s, struct cmd_ctx *ctx, int type)
{
struct args *args = self->args;
struct winlink *wl;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
struct winlink *wl;
char *layout;
template = args_get(args, 'F');
if (template == NULL) {
switch (type) {
case 0:
template = LIST_WINDOWS_TEMPLATE;
break;
case 1:
template = LIST_WINDOWS_WITH_SESSION_TEMPLATE;
break;
}
}
n = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
free(line);
format_free(ft);
n++;
layout = layout_dump(wl->window);
if (type) {
ctx->print(ctx, "%s:%d: %s [%ux%u] [layout %s]%s",
s->name, wl->idx, wl->window->name, wl->window->sx,
wl->window->sy, layout,
wl == s->curw ? " (active)" : "");
} else {
ctx->print(ctx, "%d: %s [%ux%u] [layout %s]%s",
wl->idx, wl->window->name, wl->window->sx,
wl->window->sy, layout,
wl == s->curw ? " (active)" : "");
}
xfree(layout);
}
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -79,39 +78,28 @@ bad:
return (NULL);
}
enum cmd_retval
int
cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
{
struct client *c = ctx->curclient;
struct cmd *cmd;
enum cmd_retval retval;
int guards, n;
guards = 0;
if (c != NULL && c->session != NULL)
guards = c->flags & CLIENT_CONTROL;
notify_disable();
int n, retval;
retval = 0;
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (guards)
ctx->print(ctx, "%%begin");
n = cmd_exec(cmd, ctx);
if (guards)
ctx->print(ctx, "%%end");
if ((n = cmd_exec(cmd, ctx)) == -1)
return (-1);
switch (n)
{
case CMD_RETURN_ERROR:
return (CMD_RETURN_ERROR);
case CMD_RETURN_ATTACH:
/* Client is being attached (send MSG_READY). */
retval = CMD_RETURN_ATTACH;
/*
* A 1 return value means the command client is being attached
* (sent MSG_READY).
*/
if (n == 1) {
retval = 1;
/*
* Mangle the context to treat any following commands
* as if they were called from inside.
* The command client has been attached, so mangle the
* context to treat any following commands as if they
* were called from inside.
*/
if (ctx->curclient == NULL) {
ctx->curclient = ctx->cmdclient;
@@ -121,17 +109,8 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
ctx->print = key_bindings_print;
ctx->info = key_bindings_info;
}
break;
case CMD_RETURN_YIELD:
if (retval == CMD_RETURN_NORMAL)
retval = CMD_RETURN_YIELD;
break;
case CMD_RETURN_NORMAL:
break;
}
}
notify_enable();
return (retval);
}
@@ -148,7 +127,7 @@ cmd_list_free(struct cmd_list *cmdlist)
TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
cmd_free(cmd);
}
free(cmdlist);
xfree(cmdlist);
}
size_t

View File

@@ -27,11 +27,11 @@
#include "tmux.h"
/*
* Loads a paste buffer from a file.
* Loads a session paste buffer from a file.
*/
enum cmd_retval cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_load_buffer_callback(struct client *, int, void *);
int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_load_buffer_callback(struct client *, void *);
const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb",
@@ -43,18 +43,18 @@ const struct cmd_entry cmd_load_buffer_entry = {
cmd_load_buffer_exec
};
enum cmd_retval
int
cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c = ctx->cmdclient;
struct session *s;
FILE *f;
const char *path, *newpath, *wd;
const char *path;
char *pdata, *new_pdata, *cause;
size_t psize;
u_int limit;
int ch, error, buffer, *buffer_ptr;
int ch, buffer;
int *buffer_ptr;
if (!args_has(args, 'b'))
buffer = -1;
@@ -62,42 +62,40 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
}
path = args->argv[0];
if (strcmp(path, "-") == 0) {
if (c == NULL) {
ctx->error(ctx, "%s: can't read from stdin", path);
return (-1);
}
if (c->flags & CLIENT_TERMINAL) {
ctx->error(ctx, "%s: stdin is a tty", path);
return (-1);
}
if (c->stdin_fd == -1) {
ctx->error(ctx, "%s: can't read from stdin", path);
return (-1);
}
buffer_ptr = xmalloc(sizeof *buffer_ptr);
*buffer_ptr = buffer;
error = server_set_stdin_callback (c, cmd_load_buffer_callback,
buffer_ptr, &cause);
if (error != 0) {
ctx->error(ctx, "%s: %s", path, cause);
free(cause);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_YIELD);
c->stdin_data = buffer_ptr;
c->stdin_callback = cmd_load_buffer_callback;
c->references++;
bufferevent_enable(c->stdin_event, EV_READ);
return (1);
}
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(ctx, 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) {
ctx->error(ctx, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
return (-1);
}
pdata = NULL;
@@ -123,55 +121,54 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
limit = options_get_number(&global_options, "buffer-limit");
if (buffer == -1) {
paste_add(&global_buffers, pdata, psize, limit);
return (CMD_RETURN_NORMAL);
return (0);
}
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
free(pdata);
return (CMD_RETURN_ERROR);
return (-1);
}
return (CMD_RETURN_NORMAL);
return (0);
error:
free(pdata);
if (pdata != NULL)
xfree(pdata);
if (f != NULL)
fclose(f);
return (CMD_RETURN_ERROR);
return (-1);
}
void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
cmd_load_buffer_callback(struct client *c, void *data)
{
int *buffer = data;
char *pdata;
size_t psize;
u_int limit;
if (!closed)
return;
c->stdin_callback = NULL;
c->references--;
/*
* Event callback has already checked client is not dead and reduced
* its reference count. But tell it to exit.
*/
c->flags |= CLIENT_EXIT;
psize = EVBUFFER_LENGTH(c->stdin_data);
psize = EVBUFFER_LENGTH(c->stdin_event->input);
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
free(data);
xfree(data);
return;
}
memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
bufferevent_read(c->stdin_event, pdata, psize);
pdata[psize] = '\0';
evbuffer_drain(c->stdin_data, psize);
limit = options_get_number(&global_options, "buffer-limit");
if (*buffer == -1)
paste_add(&global_buffers, pdata, psize, limit);
else if (paste_replace(&global_buffers, *buffer, pdata, psize) != 0) {
/* 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);
evbuffer_add_printf(
c->stderr_event->output, "no buffer %d\n", *buffer);
bufferevent_enable(c->stderr_event, EV_WRITE);
}
free(data);
xfree(data);
}

View File

@@ -28,7 +28,7 @@
* Lock commands.
*/
enum cmd_retval cmd_lock_server_exec(struct cmd *, struct cmd_ctx *);
int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock",
@@ -61,7 +61,7 @@ const struct cmd_entry cmd_lock_client_entry = {
};
/* ARGSUSED */
enum cmd_retval
int
cmd_lock_server_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -72,14 +72,14 @@ cmd_lock_server_exec(struct cmd *self, unused struct cmd_ctx *ctx)
server_lock();
else if (self->entry == &cmd_lock_session_entry) {
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
server_lock_session(s);
} else {
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
server_lock_client(c);
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,51 +26,41 @@
* Move a window.
*/
enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_move_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew",
"dkrs:t:", 0, 0,
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
"dks:t:", 0, 0,
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_move_window_exec
};
enum cmd_retval
int
cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *src, *dst, *s;
struct session *src, *dst;
struct winlink *wl;
char *cause;
int idx, kflag, dflag;
if (args_has(args, 'r')) {
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
session_renumber_windows(s);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
}
if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2)
return (CMD_RETURN_ERROR);
return (-1);
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
ctx->error(ctx, "can't move window: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
server_unlink_window(src, wl);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -30,8 +30,8 @@
* 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_ctx *);
int cmd_new_session_check(struct args *);
int cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
@@ -44,15 +44,15 @@ const struct cmd_entry cmd_new_session_entry = {
cmd_new_session_exec
};
enum cmd_retval
int
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);
return (-1);
return (0);
}
enum cmd_retval
int
cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -63,7 +63,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
struct termios tio, *tiop;
struct passwd *pw;
const char *newname, *target, *update, *cwd, *errstr;
char *cmd, *cause;
char *overrides, *cmd, *cause;
int detached, idx;
u_int sx, sy, i;
@@ -71,11 +71,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if (newname != NULL) {
if (!session_check_name(newname)) {
ctx->error(ctx, "bad session name: %s", newname);
return (CMD_RETURN_ERROR);
return (-1);
}
if (session_find(newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR);
return (-1);
}
}
@@ -83,7 +83,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if (target != NULL) {
groupwith = cmd_find_session(ctx, target, 0);
if (groupwith == NULL)
return (CMD_RETURN_ERROR);
return (-1);
} else
groupwith = NULL;
@@ -128,10 +128,17 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Open the terminal if necessary. */
if (!detached && ctx->cmdclient != NULL) {
if (server_client_open(ctx->cmdclient, NULL, &cause) != 0) {
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
overrides =
options_get_string(&global_s_options, "terminal-overrides");
if (tty_open(&ctx->cmdclient->tty, overrides, &cause) != 0) {
ctx->error(ctx, "open terminal failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
}
@@ -147,23 +154,15 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
}
/* Find new session size. */
if (ctx->cmdclient != NULL) {
sx = ctx->cmdclient->tty.sx;
sy = ctx->cmdclient->tty.sy;
} else if (ctx->curclient != NULL) {
sx = ctx->curclient->tty.sx;
sy = ctx->curclient->tty.sy;
} else {
if (detached) {
sx = 80;
sy = 24;
}
if (detached) {
if (args_has(args, 'x')) {
sx = strtonum(
args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "width %s", errstr);
return (CMD_RETURN_ERROR);
return (-1);
}
}
if (args_has(args, 'y')) {
@@ -171,9 +170,15 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "height %s", errstr);
return (CMD_RETURN_ERROR);
return (-1);
}
}
} else if (ctx->cmdclient != NULL) {
sx = ctx->cmdclient->tty.sx;
sy = ctx->cmdclient->tty.sy;
} else {
sx = ctx->curclient->tty.sx;
sy = ctx->curclient->tty.sy;
}
if (sy > 0 && options_get_number(&global_s_options, "status"))
sy--;
@@ -201,8 +206,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
environ_free(&env);
@@ -210,7 +215,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if (cmd != NULL && args_has(args, 'n')) {
w = s->curw->window;
window_set_name(w, args_get(args, 'n'));
xfree(w->name);
w->name = xstrdup(args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0);
}
@@ -231,13 +237,12 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
*/
if (!detached) {
if (ctx->cmdclient != NULL) {
server_write_ready(ctx->cmdclient);
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
old_s = ctx->cmdclient->session;
if (old_s != NULL)
ctx->cmdclient->last_session = old_s;
ctx->cmdclient->session = s;
notify_attached_session_changed(ctx->cmdclient);
session_update_activity(s);
server_redraw_client(ctx->cmdclient);
} else {
@@ -245,7 +250,6 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if (old_s != NULL)
ctx->curclient->last_session = old_s;
ctx->curclient->session = s;
notify_attached_session_changed(ctx->curclient);
session_update_activity(s);
server_redraw_client(ctx->curclient);
}
@@ -264,10 +268,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i);
window_copy_add(wp, "%s", cause);
free(cause);
xfree(cause);
}
ARRAY_FREE(&cfg_causes);
}
return (detached ? CMD_RETURN_NORMAL : CMD_RETURN_ATTACH);
return (!detached); /* 1 means don't tell command client to exit */
}

View File

@@ -30,33 +30,27 @@ int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww",
"ac:dF:kn:Pt:", 0, 1,
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
"[-t target-window] [command]",
"adkn:Pt:", 0, 1,
"[-adk] [-n window-name] [-t target-window] [command]",
0,
NULL,
NULL,
cmd_new_window_exec
};
enum cmd_retval
int
cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct client *c;
const char *cmd, *cwd;
const char *template;
char *cause;
int idx, last, detached;
struct format_tree *ft;
char *cp;
struct args *args = self->args;
struct session *s;
struct winlink *wl;
char *cmd, *cwd, *cause;
int idx, last, detached;
if (args_has(args, 'a')) {
wl = cmd_find_window(ctx, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
idx = wl->idx + 1;
/* Find the next free index. */
@@ -66,7 +60,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
}
if (last == INT_MAX) {
ctx->error(ctx, "no free window indexes");
return (CMD_RETURN_ERROR);
return (-1);
}
/* Move everything from last - 1 to idx up a bit. */
@@ -77,7 +71,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
}
} else {
if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2)
return (CMD_RETURN_ERROR);
return (-1);
}
detached = args_has(args, 'd');
@@ -89,7 +83,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
* Can't use session_detach as it will destroy session if this
* makes it empty.
*/
notify_window_unlinked(s, wl->window);
wl->flags &= ~WINLINK_ALERTFLAGS;
winlink_stack_remove(&s->lastw, wl);
winlink_remove(&s->windows, wl);
@@ -105,15 +98,21 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
cwd = cmd_get_default_path(ctx, args_get(args, 'c'));
cwd = options_get_string(&s->options, "default-path");
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else
cwd = s->cwd;
}
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) {
ctx->error(ctx, "create window failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
if (!detached) {
session_select(s, wl->idx);
@@ -121,23 +120,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} else
server_status_session_group(s);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = NEW_WINDOW_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(ctx, NULL)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wl->window->active);
cp = format_expand(ft, template);
ctx->print(ctx, "%s", cp);
free(cp);
format_free(ft);
}
return (CMD_RETURN_NORMAL);
if (args_has(args, 'P'))
ctx->print(ctx, "%s:%u", s->name, wl->idx);
return (0);
}

View File

@@ -27,22 +27,22 @@
* Paste paste buffer if present.
*/
enum cmd_retval cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_paste_buffer_filter(struct window_pane *,
const char *, size_t, const char *, int bracket);
void cmd_paste_buffer_filter(
struct window_pane *, const char *, size_t, const char *);
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
"db:prs:t:", 0, 0,
"[-dpr] [-s separator] [-b buffer-index] [-t target-pane]",
"db:rs:t:", 0, 0,
"[-dr] [-s separator] [-b buffer-index] [-t target-pane]",
0,
NULL,
NULL,
cmd_paste_buffer_exec
};
enum cmd_retval
int
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -52,10 +52,9 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *sepstr;
char *cause;
int buffer;
int pflag;
if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (!args_has(args, 'b'))
buffer = -1;
@@ -63,8 +62,8 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
}
@@ -74,7 +73,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer);
return (CMD_RETURN_ERROR);
return (-1);
}
}
@@ -86,9 +85,7 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
else
sepstr = "\r";
}
pflag = args_has(args, 'p') &&
(wp->screen->mode & MODE_BRACKETPASTE);
cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr, pflag);
cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr);
}
/* Delete the buffer if -d. */
@@ -99,21 +96,18 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
paste_free_index(&global_buffers, buffer);
}
return (CMD_RETURN_NORMAL);
return (0);
}
/* Add bytes to a buffer and filter '\n' according to separator. */
void
cmd_paste_buffer_filter(struct window_pane *wp,
const char *data, size_t size, const char *sep, int bracket)
cmd_paste_buffer_filter(
struct window_pane *wp, const char *data, size_t size, const char *sep)
{
const char *end = data + size;
const char *lf;
size_t seplen;
if (bracket)
bufferevent_write(wp->event, "\033[200~", 6);
seplen = strlen(sep);
while ((lf = memchr(data, '\n', end - data)) != NULL) {
if (lf != data)
@@ -124,7 +118,4 @@ cmd_paste_buffer_filter(struct window_pane *wp,
if (end != data)
bufferevent_write(wp->event, data, end - data);
if (bracket)
bufferevent_write(wp->event, "\033[201~", 6);
}

View File

@@ -31,21 +31,21 @@
* Open pipe to redirect pane output. If already open, close first.
*/
enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmd_ctx *);
int cmd_pipe_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
const struct cmd_entry cmd_pipe_pane_entry = {
"pipe-pane", "pipep",
"ot:", 0, 1,
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
CMD_TARGET_PANE_USAGE "[-o] [command]",
0,
NULL,
NULL,
cmd_pipe_pane_exec
};
enum cmd_retval
int
cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -54,9 +54,11 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
char *command;
int old_fd, pipe_fd[2], null_fd;
if ((c = cmd_find_client(ctx, NULL)) == NULL)
return (-1);
if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
c = cmd_find_client(ctx, NULL);
return (-1);
/* Destroy the old pipe. */
old_fd = wp->pipe_fd;
@@ -68,7 +70,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
/* If no pipe command, that is enough. */
if (args->argc == 0 || *args->argv[0] == '\0')
return (CMD_RETURN_NORMAL);
return (0);
/*
* With -o, only open the new pipe if there was no previous one. This
@@ -77,19 +79,19 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
* bind ^p pipep -o 'cat >>~/output'
*/
if (args_has(self->args, 'o') && old_fd != -1)
return (CMD_RETURN_NORMAL);
return (0);
/* Open the new pipe. */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) {
ctx->error(ctx, "socketpair error: %s", strerror(errno));
return (CMD_RETURN_ERROR);
return (-1);
}
/* Fork the child. */
switch (fork()) {
case -1:
ctx->error(ctx, "fork error: %s", strerror(errno));
return (CMD_RETURN_ERROR);
return (-1);
case 0:
/* Child process. */
close(pipe_fd[0]);
@@ -126,7 +128,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
bufferevent_enable(wp->pipe_event, EV_WRITE);
setblocking(wp->pipe_fd, 0);
return (CMD_RETURN_NORMAL);
return (0);
}
}

View File

@@ -24,32 +24,28 @@
* Refresh client.
*/
enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
"St:", 0, 0,
"[-S] " CMD_TARGET_CLIENT_USAGE,
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_refresh_client_exec
};
enum cmd_retval
int
cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c;
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (args_has(args, 'S')) {
status_update_jobs(c);
server_status_client(c);
} else
server_redraw_client(c);
server_redraw_client(c);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,7 +26,7 @@
* Change session name.
*/
enum cmd_retval cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
int cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename",
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_rename_session_entry = {
cmd_rename_session_exec
};
enum cmd_retval
int
cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -48,23 +48,22 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
newname = args->argv[0];
if (!session_check_name(newname)) {
ctx->error(ctx, "bad session name: %s", newname);
return (CMD_RETURN_ERROR);
return (-1);
}
if (session_find(newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR);
return (-1);
}
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
RB_REMOVE(sessions, &sessions, s);
free(s->name);
xfree(s->name);
s->name = xstrdup(newname);
RB_INSERT(sessions, &sessions, s);
server_status_session(s);
notify_session_renamed(s);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,7 +26,7 @@
* Rename a window.
*/
enum cmd_retval cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew",
@@ -38,7 +38,7 @@ const struct cmd_entry cmd_rename_window_entry = {
cmd_rename_window_exec
};
enum cmd_retval
int
cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -46,12 +46,13 @@ cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
window_set_name(wl->window, args->argv[0]);
xfree(wl->window->name);
wl->window->name = xstrdup(args->argv[0]);
options_set_number(&wl->window->options, "automatic-rename", 0);
server_status_window(wl->window);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,8 +26,8 @@
* Increase or decrease pane size.
*/
void cmd_resize_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_resize_pane_key_binding(struct cmd *, int);
int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
@@ -81,7 +81,7 @@ cmd_resize_pane_key_binding(struct cmd *self, int key)
}
}
enum cmd_retval
int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -91,7 +91,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int adjust;
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (args->argc == 0)
adjust = 1;
@@ -99,11 +99,10 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
return (-1);
}
}
layout_list_add(wp->window);
if (args_has(self->args, 'L'))
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust);
else if (args_has(self->args, 'R'))
@@ -114,5 +113,5 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
server_redraw_window(wl->window);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
@@ -28,7 +27,7 @@
* Respawn a pane (restart the command). Kill existing if -k given.
*/
enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_ctx *);
int cmd_respawn_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_pane_entry = {
"respawn-pane", "respawnp",
@@ -40,7 +39,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
cmd_respawn_pane_exec
};
enum cmd_retval
int
cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -50,19 +49,16 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
struct environ env;
const char *cmd;
char *cause;
u_int idx;
char *cause;
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
w = wl->window;
if (!args_has(self->args, 'k') && wp->fd != -1) {
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
ctx->error(ctx, "pane still active: %s:%u.%u",
s->name, wl->idx, idx);
return (CMD_RETURN_ERROR);
s->name, wl->idx, window_pane_index(w, wp));
return (-1);
}
environ_init(&env);
@@ -80,13 +76,13 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
ctx->error(ctx, "respawn pane failed: %s", cause);
free(cause);
xfree(cause);
environ_free(&env);
return (CMD_RETURN_ERROR);
return (-1);
}
wp->flags |= PANE_REDRAW;
server_status_window(w);
environ_free(&env);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,7 +18,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
@@ -27,7 +26,7 @@
* Respawn a window (restart the command). Kill existing if -k given.
*/
enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw",
@@ -39,7 +38,7 @@ const struct cmd_entry cmd_respawn_window_entry = {
cmd_respawn_window_exec
};
enum cmd_retval
int
cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -52,7 +51,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
char *cause;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
w = wl->window;
if (!args_has(self->args, 'k')) {
@@ -61,7 +60,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
continue;
ctx->error(ctx,
"window still active: %s:%d", s->name, wl->idx);
return (CMD_RETURN_ERROR);
return (-1);
}
}
@@ -82,10 +81,10 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
ctx->error(ctx, "respawn window failed: %s", cause);
free(cause);
xfree(cause);
environ_free(&env);
server_destroy_pane(wp);
return (CMD_RETURN_ERROR);
return (-1);
}
layout_init(w);
window_pane_reset_mode(wp);
@@ -97,5 +96,5 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_window(w);
environ_free(&env);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,8 +24,8 @@
* Rotate the panes in a window.
*/
void cmd_rotate_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_rotate_window_key_binding(struct cmd *, int);
int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew",
@@ -45,7 +45,7 @@ cmd_rotate_window_key_binding(struct cmd *self, int key)
args_set(self->args, 'D', NULL);
}
enum cmd_retval
int
cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -56,7 +56,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int sx, sy, xoff, yoff;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
w = wl->window;
if (args_has(self->args, 'D')) {
@@ -115,5 +115,5 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_window(w);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -29,9 +28,10 @@
* Runs a command without a window.
*/
enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_run_shell_callback(struct job *);
void cmd_run_shell_free(void *);
int cmd_run_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_run_shell_callback(struct job *);
void cmd_run_shell_free(void *);
const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run",
@@ -48,7 +48,7 @@ struct cmd_run_shell_data {
struct cmd_ctx ctx;
};
enum cmd_retval
int
cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -66,7 +66,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata);
return (CMD_RETURN_YIELD); /* don't let client exit */
return (1); /* don't let client exit */
}
void
@@ -101,7 +101,7 @@ cmd_run_shell_callback(struct job *job)
ctx->print(ctx, "%s", line);
lines++;
free(line);
xfree(line);
}
cmd = cdata->cmd;
@@ -119,7 +119,7 @@ cmd_run_shell_callback(struct job *job)
ctx->print(ctx, "%s", msg);
else
ctx->info(ctx, "%s", msg);
free(msg);
xfree(msg);
}
}
@@ -136,6 +136,6 @@ cmd_run_shell_free(void *data)
if (ctx->curclient != NULL)
ctx->curclient->references--;
free(cdata->cmd);
free(cdata);
xfree(cdata->cmd);
xfree(cdata);
}

View File

@@ -20,35 +20,33 @@
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Saves a paste buffer to a file.
* Saves a session paste buffer to a file.
*/
enum cmd_retval cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb",
"ab:", 1, 1,
"[-a] " CMD_BUFFER_USAGE " path",
"[-a] " CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_save_buffer_exec
};
enum cmd_retval
int
cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c = ctx->cmdclient;
struct session *s;
struct paste_buffer *pb;
const char *path, *newpath, *wd;
const char *path;
char *cause;
int buffer;
mode_t mask;
@@ -57,20 +55,20 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) {
ctx->error(ctx, "no buffers");
return (CMD_RETURN_ERROR);
return (-1);
}
} else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer);
return (CMD_RETURN_ERROR);
return (-1);
}
}
@@ -78,25 +76,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if (strcmp(path, "-") == 0) {
if (c == NULL) {
ctx->error(ctx, "%s: can't write to stdout", path);
return (CMD_RETURN_ERROR);
return (-1);
}
evbuffer_add(c->stdout_data, pb->data, pb->size);
server_push_stdout(c);
bufferevent_write(c->stdout_event, pb->data, pb->size);
} else {
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(ctx, 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");
@@ -105,15 +88,15 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
umask(mask);
if (f == NULL) {
ctx->error(ctx, "%s: %s", path, strerror(errno));
return (CMD_RETURN_ERROR);
return (-1);
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
ctx->error(ctx, "%s: fwrite error", path);
fclose(f);
return (CMD_RETURN_ERROR);
return (-1);
}
fclose(f);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,13 +24,13 @@
* Switch window to selected layout.
*/
void cmd_select_layout_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_layout_exec(struct cmd *, struct cmd_ctx *);
void cmd_select_layout_key_binding(struct cmd *, int);
int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl",
"nprut:", 0, 1,
"[-npUu] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
"npt:", 0, 1,
"[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
0,
cmd_select_layout_key_binding,
NULL,
@@ -76,32 +76,22 @@ cmd_select_layout_key_binding(struct cmd *self, int key)
case '5' | KEYC_ESCAPE:
self->args = args_create(1, "tiled");
break;
case 'u':
self->args = args_create(0);
args_set(self->args, 'u', NULL);
break;
case 'U':
self->args = args_create(0);
args_set(self->args, 'U', NULL);
break;
default:
self->args = args_create(0);
break;
}
}
enum cmd_retval
int
cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
const char *layoutname;
int next, previous, layout;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
return (-1);
next = self->entry == &cmd_next_layout_entry;
if (args_has(self->args, 'n'))
@@ -110,29 +100,13 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(self->args, 'p'))
previous = 1;
layout_list_add(w);
if (args_has(self->args, 'U')) {
if ((layoutname = layout_list_redo(w)) == NULL) {
ctx->info(ctx, "no more layout history");
return (CMD_RETURN_ERROR);
}
goto set_layout;
} else if (args_has(self->args, 'u')) {
if ((layoutname = layout_list_undo(w)) == NULL) {
ctx->info(ctx, "no more layout history");
return (CMD_RETURN_ERROR);
}
goto set_layout;
}
if (next || previous) {
if (next)
layout = layout_set_next(wl->window);
else
layout = layout_set_previous(wl->window);
server_redraw_window(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (CMD_RETURN_NORMAL);
return (0);
}
if (args->argc == 0)
@@ -141,21 +115,19 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
layout = layout_set_lookup(args->argv[0]);
if (layout != -1) {
layout = layout_set_select(wl->window, layout);
server_redraw_window(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (CMD_RETURN_NORMAL);
return (0);
}
if (args->argc == 0)
return (CMD_RETURN_NORMAL);
layoutname = args->argv[0];
set_layout:
if (layout_parse(wl->window, layoutname) == -1) {
ctx->error(ctx, "can't set layout: %s", layoutname);
return (CMD_RETURN_ERROR);
if (args->argc != 0) {
layoutname = args->argv[0];
if (layout_parse(wl->window, layoutname) == -1) {
ctx->error(ctx, "can't set layout: %s", layoutname);
return (-1);
}
ctx->info(ctx, "arranging in: %s", layoutname);
return (0);
}
server_redraw_window(wl->window);
ctx->info(ctx, "arranging in: %s", layoutname);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,8 +24,8 @@
* Select pane.
*/
void cmd_select_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_select_pane_key_binding(struct cmd *, int);
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
@@ -63,7 +63,7 @@ cmd_select_pane_key_binding(struct cmd *self, int key)
args_set(self->args, 't', ":.+");
}
enum cmd_retval
int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -73,26 +73,26 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (wl->window->last == NULL) {
ctx->error(ctx, "no last pane");
return (CMD_RETURN_ERROR);
return (-1);
}
window_set_active_pane(wl->window, wl->window->last);
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (CMD_RETURN_NORMAL);
return (0);
}
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (!window_pane_visible(wp)) {
ctx->error(ctx, "pane not visible");
return (CMD_RETURN_ERROR);
return (-1);
}
if (args_has(self->args, 'L'))
@@ -105,12 +105,12 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
wp = window_pane_find_down(wp);
if (wp == NULL) {
ctx->error(ctx, "pane not found");
return (CMD_RETURN_ERROR);
return (-1);
}
window_set_active_pane(wl->window, wp);
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,8 +26,8 @@
* Select window by index.
*/
void cmd_select_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_select_window_key_binding(struct cmd *, int);
int cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw",
@@ -83,7 +83,7 @@ cmd_select_window_key_binding(struct cmd *self, int key)
args_set(self->args, 'a', NULL);
}
enum cmd_retval
int
cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -104,23 +104,23 @@ cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (next || previous || last) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
return (-1);
activity = args_has(self->args, 'a');
if (next) {
if (session_next(s, activity) != 0) {
ctx->error(ctx, "no next window");
return (CMD_RETURN_ERROR);
return (-1);
}
} else if (previous) {
if (session_previous(s, activity) != 0) {
ctx->error(ctx, "no previous window");
return (CMD_RETURN_ERROR);
return (-1);
}
} else {
if (session_last(s) != 0) {
ctx->error(ctx, "no last window");
return (CMD_RETURN_ERROR);
return (-1);
}
}
@@ -128,12 +128,12 @@ cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} else {
wl = cmd_find_window(ctx, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (session_select(s, wl->idx) == 0)
server_redraw_session(s);
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -27,52 +26,34 @@
* Send keys to client.
*/
enum cmd_retval cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send",
"lRt:", 0, -1,
"[-lR] [-t target-pane] key ...",
"t:", 0, -1,
"[-t target-pane] key ...",
0,
NULL,
NULL,
cmd_send_keys_exec
};
enum cmd_retval
int
cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct window_pane *wp;
struct session *s;
struct input_ctx *ictx;
const char *str;
int i, key;
if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'R')) {
ictx = &wp->ictx;
memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
ictx->old_cx = 0;
ictx->old_cy = 0;
if (wp->mode == NULL)
screen_write_start(&ictx->ctx, wp, &wp->base);
else
screen_write_start(&ictx->ctx, NULL, &wp->base);
screen_write_reset(&ictx->ctx);
screen_write_stop(&ictx->ctx);
}
return (-1);
for (i = 0; i < args->argc; i++) {
str = args->argv[i];
if (!args_has(args, 'l') &&
(key = key_string_lookup_string(str)) != KEYC_NONE) {
if ((key = key_string_lookup_string(str)) != KEYC_NONE) {
window_pane_key(wp, s, key);
} else {
for (; *str != '\0'; str++)
@@ -80,5 +61,5 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
}
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,34 +24,31 @@
* Send prefix key as a key.
*/
enum cmd_retval cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL,
"2t:", 0, 0,
"[-2] " CMD_TARGET_PANE_USAGE,
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_send_prefix_exec
};
enum cmd_retval
int
cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct session *s;
struct window_pane *wp;
int key;
struct keylist *keylist;
if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (args_has(args, '2'))
key = options_get_number(&s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
window_pane_key(wp, s, key);
keylist = options_get_data(&s->options, "prefix");
window_pane_key(wp, s, ARRAY_FIRST(keylist));
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -30,7 +30,7 @@
* Show various information about server.
*/
enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_ctx *);
int cmd_server_info_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
@@ -43,7 +43,7 @@ const struct cmd_entry cmd_server_info_entry = {
};
/* ARGSUSED */
enum cmd_retval
int
cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{
struct tty_term *term;
@@ -88,12 +88,12 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
if (c == NULL || c->session == NULL)
continue;
ctx->print(ctx,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho "
"xterm=%u] [flags=0x%x/0x%x, references=%u]", i,
c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name,
ctx->print(ctx,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho] "
"[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.xterm_version,
c->flags, c->tty.flags, c->references);
c->tty.tio.c_cc[VERASE], c->flags,
c->tty.flags, c->references);
}
ctx->print(ctx, "%s", "");
@@ -179,5 +179,5 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
job->cmd, job->fd, job->pid, job->status);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,16 +18,15 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Add or set a paste buffer.
* Add or set a session paste buffer.
*/
enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb",
@@ -39,7 +38,7 @@ const struct cmd_entry cmd_set_buffer_entry = {
cmd_set_buffer_exec
};
enum cmd_retval
int
cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -55,22 +54,22 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if (!args_has(args, 'b')) {
paste_add(&global_buffers, pdata, psize, limit);
return (CMD_RETURN_NORMAL);
return (0);
}
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(cause);
free(pdata);
return (CMD_RETURN_ERROR);
xfree(cause);
xfree(pdata);
return (-1);
}
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
free(pdata);
return (CMD_RETURN_ERROR);
xfree(pdata);
return (-1);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,7 +27,7 @@
* Set an environment variable.
*/
enum cmd_retval cmd_set_environment_exec(struct cmd *, struct cmd_ctx *);
int cmd_set_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv",
@@ -39,7 +39,7 @@ const struct cmd_entry cmd_set_environment_entry = {
cmd_set_environment_exec
};
enum cmd_retval
int
cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -50,11 +50,11 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
name = args->argv[0];
if (*name == '\0') {
ctx->error(ctx, "empty variable name");
return (CMD_RETURN_ERROR);
return (-1);
}
if (strchr(name, '=') != NULL) {
ctx->error(ctx, "variable name contains =");
return (CMD_RETURN_ERROR);
return (-1);
}
if (args->argc < 1)
@@ -66,29 +66,29 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
env = &global_environ;
else {
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
env = &s->environ;
}
if (args_has(self->args, 'u')) {
if (value != NULL) {
ctx->error(ctx, "can't specify a value with -u");
return (CMD_RETURN_ERROR);
return (-1);
}
environ_unset(env, name);
} else if (args_has(self->args, 'r')) {
if (value != NULL) {
ctx->error(ctx, "can't specify a value with -r");
return (CMD_RETURN_ERROR);
return (-1);
}
environ_set(env, name, NULL);
} else {
if (value == NULL) {
ctx->error(ctx, "no value specified");
return (CMD_RETURN_ERROR);
return (-1);
}
environ_set(env, name, value);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,7 +27,10 @@
* Set an option.
*/
enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
int cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
int cmd_set_option_find(const char *, const struct options_table_entry **,
const struct options_table_entry **);
int cmd_set_option_unset(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
@@ -42,7 +45,7 @@ struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *,
struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_key(struct cmd *, struct cmd_ctx *,
struct options_entry *cmd_set_option_keys(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *,
@@ -60,8 +63,8 @@ struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *,
const struct cmd_entry cmd_set_option_entry = {
"set-option", "set",
"agqst:uw", 1, 2,
"[-agsquw] [-t target-session|target-window] option [value]",
"agst:uw", 1, 2,
"[-agsuw] [-t target-session|target-window] option [value]",
0,
NULL,
NULL,
@@ -70,15 +73,48 @@ const struct cmd_entry cmd_set_option_entry = {
const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw",
"agqt:u", 1, 2,
"[-agqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
"agt:u", 1, 2,
"[-agu] " CMD_TARGET_WINDOW_USAGE " option [value]",
0,
NULL,
NULL,
cmd_set_option_exec
};
enum cmd_retval
/* Look for an option in all three tables. */
int
cmd_set_option_find(
const char *optstr, const struct options_table_entry **table,
const struct options_table_entry **oe)
{
static const struct options_table_entry *tables[] = {
server_options_table,
window_options_table,
session_options_table
};
const struct options_table_entry *oe_loop;
u_int i;
for (i = 0; i < nitems(tables); i++) {
for (oe_loop = tables[i]; oe_loop->name != NULL; oe_loop++) {
if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0)
continue;
/* If already found, ambiguous. */
if (*oe != NULL)
return (-1);
*oe = oe_loop;
*table = tables[i];
/* Bail now if an exact match. */
if (strcmp((*oe)->name, optstr) == 0)
break;
}
}
return (0);
}
int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -87,7 +123,6 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl;
struct client *c;
struct options *oo;
struct window *w;
const char *optstr, *valstr;
u_int i;
@@ -95,7 +130,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
optstr = args->argv[0];
if (*optstr == '\0') {
ctx->error(ctx, "invalid option");
return (CMD_RETURN_ERROR);
return (-1);
}
if (args->argc < 2)
valstr = NULL;
@@ -104,13 +139,13 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Find the option entry, try each table. */
table = oe = NULL;
if (options_table_find(optstr, &table, &oe) != 0) {
if (cmd_set_option_find(optstr, &table, &oe) != 0) {
ctx->error(ctx, "ambiguous option: %s", optstr);
return (CMD_RETURN_ERROR);
return (-1);
}
if (oe == NULL) {
ctx->error(ctx, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR);
return (-1);
}
/* Work out the tree from the table. */
@@ -122,7 +157,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
else {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
oo = &wl->window->options;
}
} else if (table == session_options_table) {
@@ -131,33 +166,21 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
else {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
return (-1);
oo = &s->options;
}
} else {
ctx->error(ctx, "unknown table");
return (CMD_RETURN_ERROR);
return (-1);
}
/* Unset or set the option. */
if (args_has(args, 'u')) {
if (cmd_set_option_unset(self, ctx, oe, oo, valstr) != 0)
return (CMD_RETURN_ERROR);
return (-1);
} else {
if (cmd_set_option_set(self, ctx, oe, oo, valstr) != 0)
return (CMD_RETURN_ERROR);
}
/* Start or stop timers when automatic-rename changed. */
if (strcmp (oe->name, "automatic-rename") == 0) {
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
if ((w = ARRAY_ITEM(&windows, i)) == NULL)
continue;
if (options_get_number(&w->options, "automatic-rename"))
queue_window_name(w);
else if (event_initialized(&w->name_timer))
evtimer_del(&w->name_timer);
}
return (-1);
}
/* Update sizes and redraw. May not need it but meh. */
@@ -168,7 +191,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_client(c);
}
return (CMD_RETURN_NORMAL);
return (0);
}
/* Unset an option. */
@@ -188,8 +211,7 @@ cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx,
}
options_remove(oo, oe->name);
if (!args_has(args, 'q'))
ctx->info(ctx, "unset option: %s", oe->name);
ctx->info(ctx, "unset option: %s", oe->name);
return (0);
}
@@ -198,7 +220,6 @@ int
cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{
struct args *args = self->args;
struct options_entry *o;
const char *s;
@@ -215,8 +236,8 @@ cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
case OPTIONS_TABLE_NUMBER:
o = cmd_set_option_number(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_KEY:
o = cmd_set_option_key(self, ctx, oe, oo, value);
case OPTIONS_TABLE_KEYS:
o = cmd_set_option_keys(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, ctx, oe, oo, value);
@@ -235,8 +256,7 @@ cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
return (-1);
s = options_table_print_entry(oe, o);
if (!args_has(args, 'q'))
ctx->info(ctx, "set option: %s -> %s", oe->name, s);
ctx->info(ctx, "set option: %s -> %s", oe->name, s);
return (0);
}
@@ -245,7 +265,7 @@ struct options_entry *
cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{
struct args *args = self->args;
struct args *args = self->args;
struct options_entry *o;
char *oldval, *newval;
@@ -257,7 +277,7 @@ cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
o = options_set_string(oo, oe->name, "%s", newval);
free(newval);
xfree(newval);
return (o);
}
@@ -278,19 +298,31 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx,
return (options_set_number(oo, oe->name, ll));
}
/* Set a key option. */
/* Set a keys option. */
struct options_entry *
cmd_set_option_key(unused struct cmd *self, struct cmd_ctx *ctx,
cmd_set_option_keys(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{
int key;
struct keylist *keylist;
char *copy, *ptr, *s;
int key;
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
ctx->error(ctx, "bad key: %s", value);
return (NULL);
keylist = xmalloc(sizeof *keylist);
ARRAY_INIT(keylist);
ptr = copy = xstrdup(value);
while ((s = strsep(&ptr, ",")) != NULL) {
if ((key = key_string_lookup_string(s)) == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", s);
xfree(copy);
xfree(keylist);
return (NULL);
}
ARRAY_ADD(keylist, key);
}
xfree(copy);
return (options_set_number(oo, oe->name, key));
return (options_set_data(oo, oe->name, keylist, xfree));
}
/* Set a colour option. */

View File

@@ -18,15 +18,13 @@
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Show a paste buffer.
* Show a session paste buffer.
*/
enum cmd_retval cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb",
@@ -38,7 +36,7 @@ const struct cmd_entry cmd_show_buffer_entry = {
cmd_show_buffer_exec
};
enum cmd_retval
int
cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -50,25 +48,25 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int width;
if ((s = cmd_find_session(ctx, NULL, 0)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) {
ctx->error(ctx, "no buffers");
return (CMD_RETURN_ERROR);
return (-1);
}
} else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}
pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer);
return (CMD_RETURN_ERROR);
return (-1);
}
}
@@ -103,9 +101,9 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
buf[len] = '\0';
ctx->print(ctx, "%s", buf);
}
free(buf);
xfree(buf);
free(in);
xfree(in);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,19 +27,19 @@
* Show environment.
*/
enum cmd_retval cmd_show_environment_exec(struct cmd *, struct cmd_ctx *);
int cmd_show_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv",
"gt:", 0, 1,
"[-g] " CMD_TARGET_SESSION_USAGE " [name]",
"gt:", 0, 0,
"[-g] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_show_environment_exec
};
enum cmd_retval
int
cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -51,23 +51,10 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
env = &global_environ;
else {
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
env = &s->environ;
}
if (args->argc != 0) {
envent = environ_find(env, args->argv[0]);
if (envent == NULL) {
ctx->error(ctx, "unknown variable: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
if (envent->value != NULL)
ctx->print(ctx, "%s=%s", envent->name, envent->value);
else
ctx->print(ctx, "-%s", envent->name);
return (CMD_RETURN_NORMAL);
}
RB_FOREACH(envent, environ, env) {
if (envent->value != NULL)
ctx->print(ctx, "%s=%s", envent->name, envent->value);
@@ -75,5 +62,5 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "-%s", envent->name);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,7 +27,7 @@
* Show client message log.
*/
enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_ctx *);
int cmd_show_messages_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs",
@@ -39,7 +39,7 @@ const struct cmd_entry cmd_show_messages_entry = {
cmd_show_messages_exec
};
enum cmd_retval
int
cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -49,7 +49,7 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int i;
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
msg = &ARRAY_ITEM(&c->message_log, i);
@@ -60,5 +60,5 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "%s %s", tim, msg->msg);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,12 +27,12 @@
* Show options.
*/
enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmd_ctx *);
int cmd_show_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_options_entry = {
"show-options", "show",
"gst:w", 0, 1,
"[-gsw] [-t target-session|target-window] [option]",
"gst:w", 0, 0,
"[-gsw] [-t target-session|target-window]",
0,
NULL,
NULL,
@@ -41,15 +41,15 @@ const struct cmd_entry cmd_show_options_entry = {
const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw",
"gt:", 0, 1,
"[-g] " CMD_TARGET_WINDOW_USAGE " [option]",
"gt:", 0, 0,
"[-g] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_show_options_exec
};
enum cmd_retval
int
cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -71,7 +71,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
else {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
oo = &wl->window->options;
}
} else {
@@ -81,33 +81,17 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
else {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
return (-1);
oo = &s->options;
}
}
if (args->argc != 0) {
table = oe = NULL;
if (options_table_find(args->argv[0], &table, &oe) != 0) {
ctx->error(ctx, "ambiguous option: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
if (oe == NULL) {
ctx->error(ctx, "unknown option: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
for (oe = table; oe->name != NULL; oe++) {
if ((o = options_find1(oo, oe->name)) == NULL)
return (CMD_RETURN_NORMAL);
continue;
optval = options_table_print_entry(oe, o);
ctx->print(ctx, "%s %s", oe->name, optval);
} else {
for (oe = table; oe->name != NULL; oe++) {
if ((o = options_find1(oo, oe->name)) == NULL)
continue;
optval = options_table_print_entry(oe, o);
ctx->print(ctx, "%s %s", oe->name, optval);
}
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,15 +18,13 @@
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Sources a configuration file.
*/
enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
int cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_source_file_entry = {
"source-file", "source",
@@ -38,7 +36,7 @@ const struct cmd_entry cmd_source_file_entry = {
cmd_source_file_exec
};
enum cmd_retval
int
cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -61,13 +59,13 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
for (i = 0; i < ARRAY_LENGTH(&causes); i++) {
cause = ARRAY_ITEM(&causes, i);
window_copy_add(wp, "%s", cause);
free(cause);
xfree(cause);
}
} else {
for (i = 0; i < ARRAY_LENGTH(&causes); i++) {
cause = ARRAY_ITEM(&causes, i);
ctx->print(ctx, "%s", cause);
free(cause);
xfree(cause);
}
}
ARRAY_FREE(&causes);

View File

@@ -27,14 +27,13 @@
* Split a window (add a new pane).
*/
void cmd_split_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_split_window_key_binding(struct cmd *, int);
int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw",
"c:dF:l:hp:Pt:v", 0, 1,
"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
"[-t target-pane] [command]",
"dl:hp:Pt:v", 0, 1,
"[-dhvP] [-p percentage|-l size] [-t target-pane] [command]",
0,
cmd_split_window_key_binding,
NULL,
@@ -49,7 +48,7 @@ cmd_split_window_key_binding(struct cmd *self, int key)
args_set(self->args, 'h', NULL);
}
enum cmd_retval
int
cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -58,19 +57,15 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
const char *cmd, *cwd, *shell;
char *cause, *new_cause;
u_int hlimit;
char *cmd, *cwd, *cause;
const char *shell;
u_int hlimit, paneidx;
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(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
w = wl->window;
environ_init(&env);
@@ -82,7 +77,13 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
cwd = cmd_get_default_path(ctx, args_get(args, 'c'));
cwd = options_get_string(&s->options, "default-path");
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else
cwd = s->cwd;
}
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
@@ -92,18 +93,16 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (args_has(args, 'l')) {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
xasprintf(&new_cause, "size %s", cause);
free(cause);
cause = new_cause;
goto error;
ctx->error(ctx, "size %s", cause);
xfree(cause);
return (-1);
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
if (cause != NULL) {
xasprintf(&new_cause, "percentage %s", cause);
free(cause);
cause = new_cause;
goto error;
ctx->error(ctx, "percentage %s", cause);
xfree(cause);
return (-1);
}
if (type == LAYOUT_TOPBOTTOM)
size = (wp->sy * percentage) / 100;
@@ -116,7 +115,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) {
if ((lc = layout_split_pane(wp, type, size)) == NULL) {
cause = xstrdup("pane too small");
goto error;
}
@@ -138,30 +137,16 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
environ_free(&env);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = SPLIT_WINDOW_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(ctx, NULL)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, new_wp);
cp = format_expand(ft, template);
ctx->print(ctx, "%s", cp);
free(cp);
format_free(ft);
paneidx = window_pane_index(wl->window, new_wp);
ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx);
}
notify_window_layout_changed(w);
return (CMD_RETURN_NORMAL);
return (0);
error:
environ_free(&env);
if (new_wp != NULL)
window_remove_pane(w, new_wp);
ctx->error(ctx, "create pane failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
xfree(cause);
return (-1);
}

View File

@@ -24,7 +24,7 @@
* Start the server and do nothing else.
*/
enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
int cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
@@ -37,8 +37,8 @@ const struct cmd_entry cmd_start_server_entry = {
};
/* ARGSUSED */
enum cmd_retval
int
cmd_start_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx)
{
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -87,7 +87,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
free(t);
xfree(t);
break;
case '"':
if ((t = cmd_string_string(s, &p, '"', 1)) == NULL)
@@ -95,7 +95,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
free(t);
xfree(t);
break;
case '$':
if ((t = cmd_string_variable(s, &p)) == NULL)
@@ -103,7 +103,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
free(t);
xfree(t);
break;
case '#':
/* Comment: discard rest of line. */
@@ -152,7 +152,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
free(t);
xfree(t);
break;
}
/* FALLTHROUGH */
@@ -170,12 +170,13 @@ error:
xasprintf(cause, "invalid or unknown command: %s", s);
out:
free(buf);
if (buf != NULL)
xfree(buf);
if (argv != NULL) {
for (i = 0; i < argc; i++)
free(argv[i]);
free(argv);
xfree(argv[i]);
xfree(argv);
}
return (rval);
@@ -223,7 +224,7 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
free(t);
xfree(t);
continue;
}
@@ -238,7 +239,8 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
return (buf);
error:
free(buf);
if (buf != NULL)
xfree(buf);
return (NULL);
}
@@ -301,13 +303,14 @@ cmd_string_variable(const char *s, size_t *p)
buf[len] = '\0';
envent = environ_find(&global_environ, buf);
free(buf);
xfree(buf);
if (envent == NULL)
return (xstrdup(""));
return (xstrdup(envent->value));
error:
free(buf);
if (buf != NULL)
xfree(buf);
return (NULL);
}
@@ -331,7 +334,7 @@ cmd_string_expand_tilde(const char *s, size_t *p)
return (NULL);
if ((pw = getpwnam(username)) != NULL)
home = pw->pw_dir;
free(username);
xfree(username);
}
if (home == NULL)
return (NULL);

View File

@@ -27,7 +27,7 @@
* Suspend client with SIGTSTP.
*/
enum cmd_retval cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *);
int cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc",
@@ -39,18 +39,18 @@ const struct cmd_entry cmd_suspend_client_entry = {
cmd_suspend_client_exec
};
enum cmd_retval
int
cmd_suspend_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct client *c;
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
tty_stop_tty(&c->tty);
c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_SUSPEND, NULL, 0);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -26,8 +26,8 @@
* Swap two panes.
*/
void cmd_swap_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_swap_pane_key_binding(struct cmd *, int);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp",
@@ -49,7 +49,7 @@ cmd_swap_pane_key_binding(struct cmd *self, int key)
args_set(self->args, 'D', NULL);
}
enum cmd_retval
int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -61,7 +61,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
dst_wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &dst_wp);
if (dst_wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
dst_w = dst_wl->window;
if (!args_has(args, 's')) {
@@ -75,16 +75,16 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else
return (CMD_RETURN_NORMAL);
return (0);
} else {
src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
return (-1);
src_w = src_wl->window;
}
if (src_wp == dst_wp)
return (CMD_RETURN_NORMAL);
return (0);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
@@ -138,5 +138,5 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_window(src_w);
server_redraw_window(dst_w);
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -38,7 +38,7 @@ const struct cmd_entry cmd_swap_window_entry = {
cmd_swap_window_exec
};
enum cmd_retval
int
cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -50,21 +50,21 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
target_src = args_get(args, 's');
if ((wl_src = cmd_find_window(ctx, target_src, &src)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
target_dst = args_get(args, 't');
if ((wl_dst = cmd_find_window(ctx, target_dst, &dst)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
sg_src = session_group_find(src);
sg_dst = session_group_find(dst);
if (src != dst &&
sg_src != NULL && sg_dst != NULL && sg_src == sg_dst) {
ctx->error(ctx, "can't move window, sessions are grouped");
return (CMD_RETURN_ERROR);
return (-1);
}
if (wl_dst->window == wl_src->window)
return (CMD_RETURN_NORMAL);
return (0);
w = wl_dst->window;
wl_dst->window = wl_src->window;
@@ -83,5 +83,5 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -27,14 +27,14 @@
* Switch client to a different session.
*/
void cmd_switch_client_key_binding(struct cmd *, int);
enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_switch_client_key_binding(struct cmd *, int);
int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc",
"lc:npt:r", 0, 0,
"[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
"lc:npt:", 0, 0,
"[-lnp] [-c target-client] [-t target-session]",
0,
cmd_switch_client_key_binding,
NULL,
cmd_switch_client_exec
@@ -57,7 +57,7 @@ cmd_switch_client_key_binding(struct cmd *self, int key)
}
}
enum cmd_retval
int
cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -65,40 +65,30 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'r')) {
if (c->flags & CLIENT_READONLY) {
c->flags &= ~CLIENT_READONLY;
ctx->info(ctx, "made client writable");
} else {
c->flags |= CLIENT_READONLY;
ctx->info(ctx, "made client read-only");
}
}
return (-1);
s = NULL;
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
ctx->error(ctx, "can't find next session");
return (CMD_RETURN_ERROR);
return (-1);
}
} else if (args_has(args, 'p')) {
if ((s = session_previous_session(c->session)) == NULL) {
ctx->error(ctx, "can't find previous session");
return (CMD_RETURN_ERROR);
return (-1);
}
} else if (args_has(args, 'l')) {
if (c->last_session != NULL && session_alive(c->last_session))
s = c->last_session;
if (s == NULL) {
ctx->error(ctx, "can't find last session");
return (CMD_RETURN_ERROR);
return (-1);
}
} else
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
return (-1);
if (c->session != NULL)
c->last_session = c->session;
@@ -108,7 +98,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
recalculate_sizes();
server_check_unattached();
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -18,17 +18,16 @@
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Unbind key from command.
*/
enum cmd_retval cmd_unbind_key_check(struct args *);
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_ctx *, int);
int cmd_unbind_key_check(struct args *);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *, int);
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
@@ -40,50 +39,49 @@ const struct cmd_entry cmd_unbind_key_entry = {
cmd_unbind_key_exec
};
enum cmd_retval
int
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 != 0 || args_has(args, 't')))
return (-1);
if (!args_has(args, 'a') && args->argc != 1)
return (CMD_RETURN_ERROR);
return (CMD_RETURN_NORMAL);
return (-1);
return (0);
}
enum cmd_retval
int
cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct key_binding *bd;
int key;
if (!args_has(args, 'a')) {
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) {
while (!SPLAY_EMPTY(&key_bindings)) {
bd = SPLAY_ROOT(&key_bindings);
SPLAY_REMOVE(key_bindings, &key_bindings, bd);
cmd_list_free(bd->cmdlist);
xfree(bd);
}
} else
key = KEYC_NONE;
return (0);
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", args->argv[0]);
return (-1);
}
if (args_has(args, 't'))
return (cmd_unbind_key_table(self, ctx, key));
if (key == KEYC_NONE) {
while (!RB_EMPTY(&key_bindings)) {
bd = RB_ROOT(&key_bindings);
key_bindings_remove(bd->key);
}
return (CMD_RETURN_NORMAL);
}
if (!args_has(args, 'n'))
key |= KEYC_PREFIX;
key_bindings_remove(key);
return (CMD_RETURN_NORMAL);
return (0);
}
enum cmd_retval
int
cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
{
struct args *args = self->args;
@@ -94,23 +92,14 @@ cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
tablename = args_get(args, 't');
if ((mtab = mode_key_findtable(tablename)) == NULL) {
ctx->error(ctx, "unknown key table: %s", tablename);
return (CMD_RETURN_ERROR);
}
if (key == KEYC_NONE) {
while (!RB_EMPTY(mtab->tree)) {
mbind = RB_ROOT(mtab->tree);
RB_REMOVE(mode_key_tree, mtab->tree, mbind);
free(mbind);
}
return (CMD_RETURN_NORMAL);
return (-1);
}
mtmp.key = key;
mtmp.mode = !!args_has(args, 'c');
if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
RB_REMOVE(mode_key_tree, mtab->tree, mbind);
free(mbind);
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
xfree(mbind);
}
return (CMD_RETURN_NORMAL);
return (0);
}

View File

@@ -24,7 +24,7 @@
* Unlink a window, unless it would be destroyed by doing so (only one link).
*/
enum cmd_retval cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
int cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw",
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_unlink_window_entry = {
cmd_unlink_window_exec
};
enum cmd_retval
int
cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
@@ -47,7 +47,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
u_int references;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
return (-1);
w = wl->window;
sg = session_group_find(s);
@@ -60,11 +60,11 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (!args_has(self->args, 'k') && w->references == references) {
ctx->error(ctx, "window is only linked to one session");
return (CMD_RETURN_ERROR);
return (-1);
}
server_unlink_window(s, wl);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
return (0);
}

214
cmd.c
View File

@@ -20,7 +20,6 @@
#include <sys/time.h>
#include <fnmatch.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -34,9 +33,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_capture_pane_entry,
&cmd_choose_buffer_entry,
&cmd_choose_client_entry,
&cmd_choose_list_entry,
&cmd_choose_session_entry,
&cmd_choose_tree_entry,
&cmd_choose_window_entry,
&cmd_clear_history_entry,
&cmd_clock_mode_entry,
@@ -69,7 +66,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_lock_client_entry,
&cmd_lock_server_entry,
&cmd_lock_session_entry,
&cmd_move_pane_entry,
&cmd_move_window_entry,
&cmd_new_session_entry,
&cmd_new_window_entry,
@@ -123,10 +119,8 @@ struct session *cmd_lookup_session(const char *, int *);
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_ctx *,
struct window *, struct winlink **);
struct session *cmd_pane_session(struct cmd_ctx *,
struct window_pane *, struct winlink **);
struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
int cmd_find_index_offset(const char *, struct session *, int *);
struct window_pane *cmd_find_pane_offset(const char *, struct winlink *);
@@ -198,9 +192,11 @@ cmd_free_argv(int argc, char **argv)
if (argc == 0)
return;
for (i = 0; i < argc; i++)
free(argv[i]);
free(argv);
for (i = 0; i < argc; i++) {
if (argv[i] != NULL)
xfree(argv[i]);
}
xfree(argv);
}
struct cmd *
@@ -280,7 +276,7 @@ usage:
return (NULL);
}
enum cmd_retval
int
cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
{
return (cmd->entry->exec(cmd, ctx));
@@ -289,8 +285,9 @@ cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
void
cmd_free(struct cmd *cmd)
{
args_free(cmd->args);
free(cmd);
if (cmd->args != NULL)
args_free(cmd->args);
xfree(cmd);
}
size_t
@@ -302,10 +299,11 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
if (off < len) {
used = args_print(cmd->args, buf + off, len - off);
if (used == 0)
off--;
else
buf[off - 1] = '\0';
else {
off += used;
buf[off] = '\0';
buf[off] = '\0';
}
}
return (off);
}
@@ -504,7 +502,7 @@ cmd_find_client(struct cmd_ctx *ctx, const char *arg)
if (c == NULL)
ctx->error(ctx, "client not found: %s", tmparg);
free(tmparg);
xfree(tmparg);
return (c);
}
@@ -588,10 +586,6 @@ cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
*ambiguous = 0;
/* Try as a window id. */
if ((wl = cmd_lookup_winlink_windowid(s, name)) != NULL)
return (wl);
/* First see if this is a valid window index in this session. */
idx = strtonum(name, 0, INT_MAX, &errstr);
if (errstr == NULL) {
@@ -654,7 +648,10 @@ cmd_lookup_index(struct session *s, const char *name, int *ambiguous)
return (-1);
}
/* Lookup pane id. An initial % means a pane id. */
/*
* Lookup pane id. An initial % means a pane id. sp must already point to the
* current session.
*/
struct window_pane *
cmd_lookup_paneid(const char *arg)
{
@@ -670,50 +667,19 @@ cmd_lookup_paneid(const char *arg)
return (window_pane_find_by_id(paneid));
}
/* Lookup window id in a session. An initial @ means a window id. */
struct winlink *
cmd_lookup_winlink_windowid(struct session *s, const char *arg)
{
const char *errstr;
u_int windowid;
if (*arg != '@')
return (NULL);
windowid = strtonum(arg + 1, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (NULL);
return (winlink_find_by_window_id(&s->windows, windowid));
}
/* Lookup window id. An initial @ means a window id. */
struct window *
cmd_lookup_windowid(const char *arg)
{
const char *errstr;
u_int windowid;
if (*arg != '@')
return (NULL);
windowid = strtonum(arg + 1, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (NULL);
return (window_find_by_id(windowid));
}
/* Find session and winlink for window. */
/* Find session and winlink for pane. */
struct session *
cmd_window_session(struct cmd_ctx *ctx, struct window *w, struct winlink **wlp)
cmd_pane_session(struct cmd_ctx *ctx, struct window_pane *wp,
struct winlink **wlp)
{
struct session *s;
struct sessionslist ss;
struct winlink *wl;
/* If this window is in the current session, return that winlink. */
/* If this pane is in the current session, return that winlink. */
s = cmd_current_session(ctx, 0);
if (s != NULL) {
wl = winlink_find_by_window(&s->windows, w);
wl = winlink_find_by_window(&s->windows, wp->window);
if (wl != NULL) {
if (wlp != NULL)
*wlp = wl;
@@ -721,16 +687,16 @@ cmd_window_session(struct cmd_ctx *ctx, struct window *w, struct winlink **wlp)
}
}
/* Otherwise choose from all sessions with this window. */
/* Otherwise choose from all sessions with this pane. */
ARRAY_INIT(&ss);
RB_FOREACH(s, sessions, &sessions) {
if (winlink_find_by_window(&s->windows, w) != NULL)
if (winlink_find_by_window(&s->windows, wp->window) != NULL)
ARRAY_ADD(&ss, s);
}
s = cmd_choose_session_list(&ss);
ARRAY_FREE(&ss);
if (wlp != NULL)
*wlp = winlink_find_by_window(&s->windows, w);
*wlp = winlink_find_by_window(&s->windows, wp->window);
return (s);
}
@@ -740,7 +706,6 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
{
struct session *s;
struct window_pane *wp;
struct window *w;
struct client *c;
char *tmparg;
size_t arglen;
@@ -750,11 +715,9 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
if (arg == NULL)
return (cmd_current_session(ctx, prefer_unattached));
/* Lookup as pane id or window id. */
/* Lookup as pane id. */
if ((wp = cmd_lookup_paneid(arg)) != NULL)
return (cmd_window_session(ctx, wp->window, NULL));
if ((w = cmd_lookup_windowid(arg)) != NULL)
return (cmd_window_session(ctx, w, NULL));
return (cmd_pane_session(ctx, wp, NULL));
/* Trim a single trailing colon if any. */
tmparg = xstrdup(arg);
@@ -764,7 +727,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
/* An empty session name is the current session. */
if (*tmparg == '\0') {
free(tmparg);
xfree(tmparg);
return (cmd_current_session(ctx, prefer_unattached));
}
@@ -783,7 +746,7 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
ctx->error(ctx, "session not found: %s", tmparg);
}
free(tmparg);
xfree(tmparg);
return (s);
}
@@ -816,7 +779,7 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
/* Lookup as pane id. */
if ((wp = cmd_lookup_paneid(arg)) != NULL) {
s = cmd_window_session(ctx, wp->window, &wl);
s = cmd_pane_session(ctx, wp, &wl);
if (sp != NULL)
*sp = s;
return (wl);
@@ -858,7 +821,7 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
goto not_found;
if (sessptr != NULL)
free(sessptr);
xfree(sessptr);
return (wl);
no_colon:
@@ -896,7 +859,8 @@ no_session:
ctx->error(ctx, "multiple sessions: %s", arg);
else
ctx->error(ctx, "session not found: %s", arg);
free(sessptr);
if (sessptr != NULL)
xfree(sessptr);
return (NULL);
not_found:
@@ -904,7 +868,8 @@ not_found:
ctx->error(ctx, "multiple windows: %s", arg);
else
ctx->error(ctx, "window not found: %s", arg);
free(sessptr);
if (sessptr != NULL)
xfree(sessptr);
return (NULL);
}
@@ -995,7 +960,8 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1)
goto invalid_index;
free(sessptr);
if (sessptr != NULL)
xfree(sessptr);
return (idx);
no_colon:
@@ -1034,7 +1000,8 @@ no_session:
ctx->error(ctx, "multiple sessions: %s", arg);
else
ctx->error(ctx, "session not found: %s", arg);
free(sessptr);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
invalid_index:
@@ -1042,7 +1009,8 @@ invalid_index:
goto not_found;
ctx->error(ctx, "invalid index: %s", arg);
free(sessptr);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
not_found:
@@ -1050,7 +1018,8 @@ not_found:
ctx->error(ctx, "multiple windows: %s", arg);
else
ctx->error(ctx, "window not found: %s", arg);
free(sessptr);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
}
@@ -1111,7 +1080,7 @@ cmd_find_pane(struct cmd_ctx *ctx,
/* Lookup as pane id. */
if ((*wpp = cmd_lookup_paneid(arg)) != NULL) {
s = cmd_window_session(ctx, (*wpp)->window, &wl);
s = cmd_pane_session(ctx, *wpp, &wl);
if (sp != NULL)
*sp = s;
return (wl);
@@ -1144,7 +1113,7 @@ cmd_find_pane(struct cmd_ctx *ctx,
goto lookup_string;
}
free(winptr);
xfree(winptr);
return (wl);
lookup_string:
@@ -1154,7 +1123,7 @@ lookup_string:
goto error;
}
free(winptr);
xfree(winptr);
return (wl);
no_period:
@@ -1180,7 +1149,7 @@ lookup_window:
return (wl);
error:
free(winptr);
xfree(winptr);
return (NULL);
}
@@ -1243,86 +1212,3 @@ cmd_template_replace(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_ctx *ctx, const char *cwd)
{
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(ctx, 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 (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
root = ctx->cmdclient->cwd;
else if (ctx->curclient != NULL && 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);
}

View File

@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -40,7 +41,7 @@ struct colour_rgb {
struct colour_rgb *colour_rgb_256;
void colour_rgb_generate256(void);
u_int colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
double colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
int colour_rgb_find(struct colour_rgb *);
/* Generate 256 colour RGB table. */
@@ -90,7 +91,7 @@ colour_rgb_generate256(void)
}
/* Get colour RGB distance. */
u_int
double
colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
{
int r, g, b;
@@ -98,20 +99,21 @@ colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
r = rgb1->r - rgb2->r;
g = rgb1->g - rgb2->g;
b = rgb1->b - rgb2->b;
return (r * r + g * g + b * b);
return (sqrt(r * r + g * g + b * b));
}
/* Work out the nearest colour from the 256 colour set. */
int
colour_rgb_find(struct colour_rgb *rgb)
{
u_int distance, lowest, colour, i;
double distance, lowest;
u_int colour, i;
if (colour_rgb_256 == NULL)
colour_rgb_generate256();
colour = 16;
lowest = UINT_MAX;
lowest = INFINITY;
for (i = 0; i < 240; i++) {
distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
if (distance < lowest) {
@@ -170,22 +172,6 @@ colour_tostring(int c)
return ("white");
case 8:
return ("default");
case 90:
return ("brightblack");
case 91:
return ("brightred");
case 92:
return ("brightgreen");
case 93:
return ("brightyellow");
case 94:
return ("brightblue");
case 95:
return ("brightmagenta");
case 96:
return ("brightcyan");
case 97:
return ("brightwhite");
}
return (NULL);
}
@@ -235,30 +221,6 @@ colour_fromstring(const char *s)
return (7);
if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
return (8);
if (strcasecmp(s, "brightblack") == 0 ||
(s[0] == '9' && s[1] == '0' && s[1] == '\0'))
return (90);
if (strcasecmp(s, "brightred") == 0 ||
(s[0] == '9' && s[1] == '1' && s[1] == '\0'))
return (91);
if (strcasecmp(s, "brightgreen") == 0 ||
(s[0] == '9' && s[1] == '2' && s[1] == '\0'))
return (92);
if (strcasecmp(s, "brightyellow") == 0 ||
(s[0] == '9' && s[1] == '3' && s[1] == '\0'))
return (93);
if (strcasecmp(s, "brightblue") == 0 ||
(s[0] == '9' && s[1] == '4' && s[1] == '\0'))
return (94);
if (strcasecmp(s, "brightmagenta") == 0 ||
(s[0] == '9' && s[1] == '5' && s[1] == '\0'))
return (95);
if (strcasecmp(s, "brightcyan") == 0 ||
(s[0] == '9' && s[1] == '6' && s[1] == '\0'))
return (96);
if (strcasecmp(s, "brightwhite") == 0 ||
(s[0] == '9' && s[1] == '7' && s[1] == '\0'))
return (97);
return (-1);
}

View File

@@ -196,11 +196,6 @@ size_t strlcat(char *, const char *, size_t);
int daemon(int, int);
#endif
#ifndef HAVE_B64_NTOP
/* b64_ntop.c */
int b64_ntop(const char *, size_t, char *, size_t);
#endif
#ifndef HAVE_FORKPTY
/* forkpty.c */
#include <sys/ioctl.h>

View File

@@ -44,16 +44,13 @@ int
vasprintf(char **ret, const char *fmt, va_list ap)
{
int n;
va_list ap2;
va_copy(ap2, ap);
if ((n = vsnprintf(NULL, 0, fmt, ap)) < 0)
goto error;
*ret = xmalloc(n + 1);
if ((n = vsnprintf(*ret, n + 1, fmt, ap2)) < 0) {
free(*ret);
if ((n = vsnprintf(*ret, n + 1, fmt, ap)) < 0) {
xfree(*ret);
goto error;
}

View File

@@ -1,182 +0,0 @@
/*
* Copyright (c) 1996, 1998 by Internet Software Consortium.
*
* 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
* permission under its copyrights to use, copy, modify, and distribute this
* Software with or without fee, provided that the above copyright notice and
* all paragraphs of this notice appear in all copies, and that the name of IBM
* not be used in connection with the marketing of any product incorporating
* the Software or modifications thereof, without specific, written prior
* permission.
*
* To the extent it has a right to do so, IBM grants an immunity from suit
* under its patents, if any, for the use, sale or manufacture of products to
* the extent that such products are used for performing Domain Name System
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
* granted for any product per se or for any other function of any product.
*
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Assert(Cond) if (!(Cond)) abort()
static const char Base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
The following encoding technique is taken from RFC 1521 by Borenstein
and Freed. It is reproduced here in a slightly edited form for
convenience.
A 65-character subset of US-ASCII is used, enabling 6 bits to be
represented per printable character. (The extra 65th character, "=",
is used to signify a special processing function.)
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
Each 6-bit group is used as an index into an array of 64 printable
characters. The character referenced by the index is placed in the
output string.
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
Special processing is performed if fewer than 24 bits are available
at the end of the data being encoded. A full encoding quantum is
always completed at the end of a quantity. When fewer than 24 input
bits are available in an input group, zero bits are added (on the
right) to form an integral number of 6-bit groups. Padding at the
end of the data is performed using the '=' character.
Since all base64 input is an integral number of octets, only the
-------------------------------------------------
following cases can arise:
(1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded
output will be an integral multiple of 4 characters
with no "=" padding,
(2) the final quantum of encoding input is exactly 8 bits;
here, the final unit of encoded output will be two
characters followed by two "=" padding characters, or
(3) the final quantum of encoding input is exactly 16 bits;
here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
int
b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
size_t datalength = 0;
uint8_t input[3];
uint8_t output[4];
size_t i;
while (2 < srclength) {
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclength -= 3;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
Assert(output[3] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}
/* Now we worry about padding. */
if (0 != srclength) {
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
input[i] = *src++;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
if (srclength == 1)
target[datalength++] = Pad64;
else
target[datalength++] = Base64[output[2]];
target[datalength++] = Pad64;
}
if (datalength >= targsize)
return (-1);
target[datalength] = '\0'; /* Returned value doesn't count \0. */
return (datalength);
}

View File

@@ -43,7 +43,9 @@
#include "tmux.h"
char *
fgetln(FILE *fp, size_t *len)
fgetln(fp, len)
FILE *fp;
size_t *len;
{
static char *buf = NULL;
static size_t bufsiz = 0;

View File

@@ -52,7 +52,10 @@ char *BSDoptarg; /* argument associated with option */
* Parse argc/argv argument vector.
*/
int
BSDgetopt(int nargc, char *const *nargv, const char *ostr)
BSDgetopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */

View File

@@ -1,4 +1,5 @@
/* $OpenBSD: queue.h,v 1.36 2012/04/11 13:29:14 naddy Exp $ */
/* $Id$ */
/* $OpenBSD: queue.h,v 1.31 2005/11/25 08:06:25 otto Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
@@ -36,7 +37,7 @@
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
*
@@ -82,7 +83,7 @@
* For details on the use of these macros, see the queue(3) manual page.
*/
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
#ifdef QUEUE_MACRO_DEBUG
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
#else
#define _Q_INVALIDATE(a)
@@ -95,15 +96,15 @@
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
@@ -117,10 +118,10 @@ struct { \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST(head); \
(var) && ((tvar) = SLIST_NEXT(var, field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != SLIST_END(head); \
(varp) = &SLIST_NEXT((var), field))
/*
* Singly-linked List functions.
@@ -139,7 +140,7 @@ struct { \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
#define SLIST_REMOVE_NEXT(head, elm, field) do { \
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
} while (0)
@@ -191,11 +192,6 @@ struct { \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST(head); \
(var) && ((tvar) = LIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* List functions.
*/
@@ -274,11 +270,6 @@ struct { \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SIMPLEQ_FIRST(head); \
(var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Simple queue functions.
*/
@@ -310,12 +301,6 @@ struct { \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
== NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
/*
* Tail queue definitions.
*/
@@ -334,8 +319,8 @@ struct { \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* tail queue access methods
/*
* tail queue access methods
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
@@ -353,24 +338,11 @@ struct { \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_NEXT(var, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/*
* Tail queue functions.
*/
@@ -455,7 +427,7 @@ struct { \
}
/*
* Circular queue access methods
* Circular queue access methods
*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
@@ -470,23 +442,11 @@ struct { \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_NEXT(var, field))
#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = CIRCLEQ_FIRST(head); \
(var) != CIRCLEQ_END(head) && \
((tvar) = CIRCLEQ_NEXT(var, field), 1); \
(var) = (tvar))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for((var) = CIRCLEQ_LAST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_PREV(var, field))
#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = CIRCLEQ_LAST(head, headname); \
(var) != CIRCLEQ_END(head) && \
((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/*
* Circular queue functions.
*/

View File

@@ -1,5 +1,5 @@
/* $Id$ */
/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */
/* $OpenBSD: tree.h,v 1.12 2009/03/02 09:42:55 mikeb Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -84,7 +84,7 @@ struct { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
@@ -731,19 +731,9 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \
(x) = (y))
#endif /* _SYS_TREE_H_ */

View File

@@ -1,7 +1,7 @@
# $Id$
# Miscellaneous autofoo bullshit.
AC_INIT(tmux, 1.7)
AC_INIT(tmux, 1.5)
AC_CONFIG_AUX_DIR(etc)
AM_INIT_AUTOMAKE([foreign])
@@ -12,7 +12,6 @@ AC_CANONICAL_HOST
# autoconf will automatically use CFLAGS="-O2 -g". Prevent that by using an
# empty default.
: ${CFLAGS=""}
# Set up the compiler in two different ways and say yes we may want to install.
AC_PROG_CC
AM_PROG_CC_C_O
@@ -53,8 +52,9 @@ AM_CONDITIONAL(IS_DEBUG, test "x$found_debug" = xyes)
AC_ARG_ENABLE(
static,
AC_HELP_STRING(--enable-static, create a static build),
[LDFLAGS="$LDFLAGS -static"]
[found_static=$enable_static]
)
AM_CONDITIONAL(IS_STATIC, test "x" = xyes)
# Is this gcc?
AM_CONDITIONAL(IS_GCC, test "x$GCC" = xyes)
@@ -102,28 +102,12 @@ AM_CONDITIONAL(IS_GLIBC, test "x$found_glibc" = xyes)
AC_MSG_RESULT($found_glibc)
# Look for clock_gettime. Must come before event_init.
AC_SEARCH_LIBS(clock_gettime, rt)
AC_CHECK_LIB(rt, clock_gettime)
# Look for libevent.
PKG_CHECK_MODULES(
LIBEVENT,
libevent,
[
CPPFLAGS="$LIBEVENT_CFLAGS $CPPFLAGS"
LIBS="$LIBEVENT_LIBS $LIBS"
found_libevent=yes
],
[
AC_SEARCH_LIBS(
event_init,
[event event-1.4 event2],
found_libevent=yes,
found_libevent=no
)
]
)
AC_SEARCH_LIBS(event_init, [event event-1.4 event2], found_libevent=yes, found_libevent=no)
if test "x$found_libevent" = xno; then
AC_MSG_ERROR("libevent not found")
AC_MSG_ERROR("libevent not found")
fi
# Look for curses.
@@ -137,48 +121,16 @@ if test "x$found_curses" = xno; then
AC_MSG_ERROR("curses not found")
fi
# Check for b64_ntop.
AC_MSG_CHECKING(for b64_ntop)
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
if test "x$found_b64_ntop" = xno; then
AC_MSG_RESULT(no)
AC_MSG_CHECKING(for b64_ntop with -lresolv)
LIBS="$LIBS -lresolv"
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
if test "x$found_b64_ntop" = xno; then
AC_MSG_RESULT(no)
fi
fi
if test "x$found_b64_ntop" = xyes; then
AC_DEFINE(HAVE_B64_NTOP)
AC_MSG_RESULT(yes)
fi
AM_CONDITIONAL(NO_B64_NTOP, [test "x$found_b64_ntop" = xno])
# Look for networking libraries.
AC_SEARCH_LIBS(b64_ntop, resolv)
AC_SEARCH_LIBS(__b64_ntop, resolv)
AC_SEARCH_LIBS(inet_ntoa, nsl)
AC_SEARCH_LIBS(socket, socket)
AC_CHECK_LIB(xnet, socket)
# Look for sqrt.
AC_SEARCH_LIBS(sqrt, m)
# Check for CMSG_DATA. Some platforms require _XOPEN_SOURCE_EXTENDED (for
# example see xopen_networking(7) on HP-UX).
XOPEN_DEFINES=
@@ -339,7 +291,6 @@ AM_CONDITIONAL(NO_GETOPT, [test "x$found_getopt" = xno])
AC_CHECK_FUNCS(
[ \
bzero \
dirfd \
setproctitle \
sysconf \
]
@@ -347,7 +298,7 @@ AC_CHECK_FUNCS(
# Check for BSD-style integer types.
AC_MSG_CHECKING(for BSD-style unsigned types)
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
AC_COMPILE_IFELSE(
[
#include <sys/types.h>
#ifdef HAVE_STDINT_H
@@ -357,7 +308,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
#endif
int main(void)
{ u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; }
])],
],
[AC_DEFINE(HAVE_BSD_TYPES) AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no)
)
@@ -381,7 +332,7 @@ fi
# Look for __progname.
AC_MSG_CHECKING(for __progname)
AC_LINK_IFELSE([AC_LANG_SOURCE(
AC_LINK_IFELSE(
[
#include <stdio.h>
#include <stdlib.h>
@@ -391,7 +342,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE(
printf("%s\n", cp);
exit(0);
}
])],
],
[AC_DEFINE(HAVE___PROGNAME) AC_MSG_RESULT(yes)],
AC_MSG_RESULT(no)
)
@@ -413,6 +364,15 @@ else
AC_MSG_RESULT(no)
fi
# Look for /proc/$$/fd.
AC_MSG_CHECKING(for /proc/\$\$/fd)
if test -d /proc/$$/fd; then
AC_DEFINE(HAVE_DIRFD)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
# Figure out the platform for osdep-*.c and forkpty-*.c.
AC_MSG_CHECKING(platform)
case "$host_os" in
@@ -425,15 +385,11 @@ case "$host_os" in
AC_DEFINE(BROKEN_CMSG_FIRSTHDR)
PLATFORM=darwin
;;
*dragonfly*)
AC_MSG_RESULT(dragonfly)
PLATFORM=dragonfly
;;
*linux*)
AC_MSG_RESULT(linux)
PLATFORM=linux
;;
*freebsd*)
*freebsd*|*dragonfly*)
AC_MSG_RESULT(freebsd)
PLATFORM=freebsd
;;
@@ -465,7 +421,6 @@ esac
AC_SUBST(PLATFORM)
AM_CONDITIONAL(IS_AIX, test "x$PLATFORM" = xaix)
AM_CONDITIONAL(IS_DARWIN, test "x$PLATFORM" = xdarwin)
AM_CONDITIONAL(IS_DRAGONFLY, test "x$PLATFORM" = xdragonfly)
AM_CONDITIONAL(IS_LINUX, test "x$PLATFORM" = xlinux)
AM_CONDITIONAL(IS_FREEBSD, test "x$PLATFORM" = xfreebsd)
AM_CONDITIONAL(IS_NETBSD, test "x$PLATFORM" = xnetbsd)

View File

@@ -1,212 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
*
* 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 "tmux.h"
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
((c) != NULL && ((c)->flags & CLIENT_CONTROL))
void
control_notify_input(struct client *c, struct window_pane *wp,
struct evbuffer *input)
{
u_char *buf;
size_t len;
struct evbuffer *message;
u_int i;
if (c->session == NULL)
return;
buf = EVBUFFER_DATA(input);
len = EVBUFFER_LENGTH(input);
/*
* Only write input if the window pane is linked to a window belonging
* to the client's session.
*/
if (winlink_find_by_window(&c->session->windows, wp->window) != NULL) {
message = evbuffer_new();
evbuffer_add_printf(message, "%%output %%%u ", wp->id);
for (i = 0; i < len; i++)
evbuffer_add_printf(message, "%02hhx", buf[i]);
control_write_buffer(c, message);
evbuffer_free(message);
}
}
void
control_notify_window_layout_changed(struct window *w)
{
struct client *c;
struct session *s;
struct format_tree *ft;
struct winlink *wl;
u_int i;
const char *template;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
s = c->session;
if (winlink_find_by_window_id(&s->windows, w->id) == NULL)
continue;
/*
* When the last pane in a window is closed it won't have a
* layout root and we don't need to inform the client about the
* layout change because the whole window will go away soon.
*/
if (w->layout_root == NULL)
continue;
template = "%layout-change #{window_id} #{window_layout}";
ft = format_create();
wl = winlink_find_by_window(&s->windows, w);
if (wl != NULL) {
format_winlink(ft, c->session, wl);
control_write(c, "%s", format_expand(ft, template));
}
format_free(ft);
}
}
void
control_notify_window_unlinked(unused struct session *s, struct window *w)
{
struct client *c;
struct session *cs;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
cs = c->session;
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
control_write(c, "%%window-close %u", w->id);
else
control_write(c, "%%unlinked-window-close %u", w->id);
}
}
void
control_notify_window_linked(unused struct session *s, struct window *w)
{
struct client *c;
struct session *cs;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
cs = c->session;
if (winlink_find_by_window_id(&cs->windows, w->id) != NULL)
control_write(c, "%%window-add %u", w->id);
else
control_write(c, "%%unlinked-window-add %u", w->id);
}
}
void
control_notify_window_renamed(struct window *w)
{
struct client *c;
struct session *s;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
s = c->session;
if (winlink_find_by_window_id(&s->windows, w->id) != NULL) {
control_write(c, "%%window-renamed %u %s",
w->id, w->name);
} else {
control_write(c, "%%unlinked-window-renamed %u %s",
w->id, w->name);
}
}
}
void
control_notify_attached_session_changed(struct client *c)
{
struct session *s;
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
return;
s = c->session;
control_write(c, "%%session-changed %d %s", s->idx, s->name);
}
void
control_notify_session_renamed(struct session *s)
{
struct client *c;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session != s)
continue;
control_write(c, "%%session-renamed %s", s->name);
}
}
void
control_notify_session_created(unused struct session *s)
{
struct client *c;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
control_write(c, "%%sessions-changed");
}
}
void
control_notify_session_close(unused struct session *s)
{
struct client *c;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
continue;
control_write(c, "%%sessions-changed");
}
}

130
control.c
View File

@@ -1,130 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
*
* 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 <event.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
void printflike2 control_msg_error(struct cmd_ctx *, const char *, ...);
void printflike2 control_msg_print(struct cmd_ctx *, const char *, ...);
void printflike2 control_msg_info(struct cmd_ctx *, const char *, ...);
/* Command error callback. */
void printflike2
control_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
{
struct client *c = ctx->curclient;
va_list ap;
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);
}
/* Command print callback. */
void printflike2
control_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
{
struct client *c = ctx->curclient;
va_list ap;
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);
}
/* Command info callback. */
void printflike2
control_msg_info(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
{
}
/* Write a line. */
void printflike2
control_write(struct client *c, const char *fmt, ...)
{
va_list ap;
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);
}
/* Write a buffer, adding a terminal newline. Empties buffer. */
void
control_write_buffer(struct client *c, struct evbuffer *buffer)
{
evbuffer_add_buffer(c->stdout_data, buffer);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
}
/* Control input callback. Read lines and fire commands. */
void
control_callback(struct client *c, int closed, unused void *data)
{
char *line, *cause;
struct cmd_ctx ctx;
struct cmd_list *cmdlist;
if (closed)
c->flags |= CLIENT_EXIT;
for (;;) {
line = evbuffer_readln(c->stdin_data, NULL, EVBUFFER_EOL_LF);
if (line == NULL)
break;
if (*line == '\0') { /* empty line exit */
c->flags |= CLIENT_EXIT;
break;
}
ctx.msgdata = NULL;
ctx.cmdclient = NULL;
ctx.curclient = c;
ctx.error = control_msg_error;
ctx.print = control_msg_print;
ctx.info = control_msg_info;
if (cmd_string_parse(line, &cmdlist, &cause) != 0) {
control_write(c, "%%error in line \"%s\": %s", line,
cause);
free(cause);
} else {
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
free(line);
}
}

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