371 Commits
0.9 ... 1.0

Author SHA1 Message Date
no_author
be20fc8699 This commit was manufactured by cvs2svn to create tag 'TMUX_1_0'. 2009-09-20 18:54:22 +00:00
Nicholas Marriott
f82598ca2d 1.0. 2009-09-20 18:54:21 +00:00
Nicholas Marriott
b29d4affd8 Don't try to use tio if it is NULL. 2009-09-20 18:31:16 +00:00
Nicholas Marriott
6594af3729 These are done. 2009-09-20 17:52:39 +00:00
Nicholas Marriott
6df9ac7c37 FreeBSD tree.h is fine. 2009-09-20 17:51:54 +00:00
Tiago Cunha
73f58b90a0 Update. 2009-09-19 18:53:56 +00:00
Tiago Cunha
23d7ed3187 Sync OpenBSD patchset 331:
New option, set-titles-string, to allow the window title to be specified (as
for status-left/right) if set-titles is on. Also only update the title when the
status line is being redrawn.
2009-09-19 18:53:01 +00:00
Nicholas Marriott
a2e03ce3cb Add some bits. 2009-09-18 14:19:18 +00:00
Nicholas Marriott
15b643fc11 Sync from OpenBSD:
==
Rather than constructing an entire termios struct from ttydefaults.h, just let
forkpty do it and then alter the bits that should be changed after fork. A
little neater and more portable.
==

This should fix problems caused by glibc's broken ttydefaults.h file.
2009-09-16 12:36:28 +00:00
Tiago Cunha
150fba5ecd Sync OpenBSD patchset 329:
Enclose repeated buffer draining code in a new msgbuf_drain()
function, which is additionally exported for use by others.

From nicm@, who reminded me that tmux is now using buffer.c, too.
2009-09-15 23:59:40 +00:00
Tiago Cunha
c507bf25de Sync OpenBSD patchset 328:
Stick line length to what is actually used (removing an optimization that
allowed it to be bigger), and use clear line/EOL sequences rather than spaces
in copy/scroll mode.

This fixes xterm copy/paste from tmux which treats trailing spaces differently
from clearing a line with the escape sequences. Reported by martynas@.
2009-09-15 23:54:57 +00:00
Tiago Cunha
dbaa28492e Sync OpenBSD patchset 327:
The default terminal size should be 80x24, not 80x25.
2009-09-15 23:52:30 +00:00
Tiago Cunha
960cd3da69 Sync OpenBSD patchset 326:
Nuke unused server_client_index function, pointed out by martynas@.
2009-09-15 23:50:32 +00:00
Nicholas Marriott
82d6bab57c +. 2009-09-15 19:02:35 +00:00
Nicholas Marriott
24baf14e53 Update. 2009-09-15 07:43:25 +00:00
Tiago Cunha
5fcf7149d4 Always set VERASE to \177. 2009-09-13 20:56:52 +00:00
Tiago Cunha
4d4ec52df8 Zap unused variables. 2009-09-13 20:43:21 +00:00
Tiago Cunha
69e7f4af19 Sync OpenBSD patchset 324:
Tidy some common code for destroying sessions into a new function.
2009-09-13 20:37:37 +00:00
Tiago Cunha
61990deb36 Sync OpenBSD patchset 323:
tmux always outputs \177 for backspace, so explicitly set VERASE to \177 for
new windows.
2009-09-13 20:30:12 +00:00
Tiago Cunha
0ec1ce005c Sync OpenBSD patchset 322:
Permit options such as status-bg to be configured using the entire 256 colour
palette by setting "colour0" to "colour255".
2009-09-11 14:13:52 +00:00
Tiago Cunha
f0cb57d8ac Sync OpenBSD patchset 321:
While the display-panes indicator is on screen, make the number keys select the
pane with that index.
2009-09-08 00:01:11 +00:00
Tiago Cunha
930f67f474 Sync OpenBSD patchset 320:
Reference count clients and sessions rather than relying on a saved index for
cmd-choose-*.
2009-09-07 23:59:19 +00:00
Tiago Cunha
1de812d5a8 Sync OpenBSD patchset 319:
Tiny cleanup.

ok nicm@
2009-09-07 23:50:07 +00:00
Tiago Cunha
c272de7cba Sync OpenBSD patchset 318:
Give each paste buffer a size member instead of requiring them to be
zero-terminated.
2009-09-07 23:48:54 +00:00
Tiago Cunha
5edc465802 Sync OpenBSD patchset 317:
Permit embedded colour and attributes in status-left and status-right using new
#[] special characters, for example #[fg=red,bg=blue,blink].
2009-09-07 23:37:48 +00:00
Nicholas Marriott
ec195a4e15 +. 2009-09-07 15:41:52 +00:00
Tiago Cunha
bb2d57dcbf Sync OpenBSD patchset 316:
Only redraw all clients once when the backoff timer expires rather than every
second all the time.

Reported by Simon Nicolussi.
2009-09-05 19:03:41 +00:00
Tiago Cunha
02c4760ace Sync OpenBSD patchset 315:
Tidy main and make it a bit easier to read.
2009-09-04 20:37:40 +00:00
Tiago Cunha
51a1f25247 Sync OpenBSD patchset 314:
Tell the user when sleeping due to password backoff.
2009-09-04 20:27:06 +00:00
Nicholas Marriott
895efe7b05 Solaris needs a knob twiddled to get POSIX getpwduid_r. 2009-09-04 14:48:25 +00:00
Tiago Cunha
83f5581da4 Sync OpenBSD patchset 313:
Fix a race condition when asking a client to take over the terminal (switching
to a different poll loop):

If a MSG_READY was followed very quickly by a MSG_EXIT (for example if doing
"tmux new 'exit'"), both messages could be read as part of the same imsg_read
in the first client poll loop. The MSG_READY would then cause a switch to the
second client loop, which would immediately call poll(2) again, causing the
client to hang forever waiting for an exit message that it already had.

Change to call imsg_get to process any existing messages before polling.
2009-09-03 21:06:30 +00:00
Tiago Cunha
884ebb6dab Sync OpenBSD patchset 309:
Accept -l to make it easier for people who use tmux as a login shell to use
$SHELL. Originally from martynas@, tweaked by me.
2009-09-03 21:02:55 +00:00
Tiago Cunha
c274551db6 - Make it compile on operating systems other than BSD due to OpenBSD patchset
308.
- While there, remove some duplicate code from the compat header file.
2009-09-03 20:54:39 +00:00
Tiago Cunha
f796336a12 Sync OpenBSD patchset 308:
When incorrect passwords are entered, behave similarly to login(1) and backoff
for a bit. Based on a diff from martynas@.
2009-09-03 20:44:38 +00:00
Tiago Cunha
3b944fe7e8 Sync OpenBSD patchset 307:
Add a transpose-chars command in edit mode (C-t in emacs mode only). From Kalle
Olavi Niemitalo.
2009-09-02 22:45:17 +00:00
Nicholas Marriott
afd0bd7cb0 When shutting down the server, expect clients to be polite and exit when asked
with the right message.
2009-09-02 21:36:00 +00:00
Nicholas Marriott
a5c17d77bf Nuke debugging. 2009-09-02 20:17:23 +00:00
Nicholas Marriott
d33caca6c7 That was the wrong fix. MSG_ERROR should set the error and the client should
use the error and exit on MSG_EXIT (it was being handled in the default
case). Undo the last change, move the errstr check into the MSG_EXIT case, and
add a comment.
2009-09-02 20:16:29 +00:00
Nicholas Marriott
c23bde74ec Set exittype for error exit as well as the error string. 2009-09-02 20:01:22 +00:00
Nicholas Marriott
ecffcf1667 Update. 2009-09-02 19:33:47 +00:00
Nicholas Marriott
26682256b3 OS X CMSG_FIRSTHDR is broken. 2009-09-02 12:30:56 +00:00
Tiago Cunha
5838ee1263 Sync OpenBSD patchset 306:
If forking a login shell or if SHELL is otherwise not useful, set it to the
default shell. Based on a diff from martynas@.
2009-09-02 01:08:32 +00:00
Tiago Cunha
b7cb7d10f9 Update. 2009-09-02 01:06:30 +00:00
Tiago Cunha
521659db4b Adjust OpenBSD patchset 305 to the portable version. 2009-09-02 01:05:55 +00:00
Tiago Cunha
a3a150faf2 Sync OpenBSD patchset 305:
When using tmux as a login shell, there is currently no way to specify a shell
to be used as a login shell inside tmux, so add a default-shell session option.
This sets the shell invoked as a login shell when the default-command option is
empty.

The default option value is whichever of $SHELL, getpwuid(getuid())'s pw_shell
or /bin/sh is valid first.

Based on a diff from martynas@, changed by me to be a session option rather
than a window option.
2009-09-02 01:02:44 +00:00
Tiago Cunha
ce5c441f0f Sync OpenBSD patchset 304:
Use "Password:" with no space for password prompts and don't display a *s for
the password, like pretty much everything else. From martynas@ with minor
tweaks by me.
2009-09-02 00:55:49 +00:00
Tiago Cunha
99de03ea32 Sync OpenBSD patchset 303:
Sort cases same as getopt argument, from martynas.
2009-09-02 00:54:00 +00:00
Tiago Cunha
d463eddb8b Update. 2009-08-31 22:31:44 +00:00
Tiago Cunha
ed3535db8a Sync OpenBSD patchset 302:
Add a new display-panes command, with two options (display-panes-colour and
display-panes-time), which displays a visual indication of the number of each
pane.
2009-08-31 22:30:15 +00:00
Tiago Cunha
2fe369831c Sync OpenBSD patchset 301:
squash typo
2009-08-31 22:25:33 +00:00
Tiago Cunha
86fb9737dc Sync OpenBSD patchset 300:
Don't call tty_free unless the client is a terminal, otherwise tty_init hasn't
been called and it may end up doing close(0). From Kalle Olavi Niemitalo.
2009-08-31 22:24:18 +00:00
Tiago Cunha
d15e88cb68 Sync OpenBSD patchset 299:
Initialise the arg2 pointer properly (also free it when freeing the
others). Fixes crashes with J in malloc_options reported by oga.
2009-08-26 22:13:52 +00:00
Tiago Cunha
83e44c7d8e Sync OpenBSD patchset 298:
Make this work when the clock is in small characters as well. Doh.
2009-08-26 22:12:21 +00:00
Tiago Cunha
fde3bda453 Sync OpenBSD patchset 297:
Fix clock mode in black and white terminals now that tty.c tries to fix
reverse.
2009-08-26 22:11:00 +00:00
Nicholas Marriott
1a5aba47c7 ttydefchars is a fucking horlicks. Happily we only need it in one file, move it
in there to avoid multiple inclusion issues.

Perhaps it would be better to pass NULL through to forkpty in the default
case...
2009-08-26 09:10:47 +00:00
Nicholas Marriott
6b4ed722b1 FreeBSD and NetBSD HAVE got ttydefaults.h. Fixes SF bug 2844744.
Also make clang use -iquote in makefiles.
2009-08-26 08:58:39 +00:00
Tiago Cunha
1ce325b31e Sync OpenBSD patchset 296:
Print -l and -p when showing command, pointed out by Tiago Cunha.
2009-08-25 16:52:42 +00:00
Tiago Cunha
f5d38f2696 Update. 2009-08-25 16:50:34 +00:00
Tiago Cunha
bd5b011ecd Include <ctype.h>. 2009-08-25 13:55:29 +00:00
Tiago Cunha
8fd77cbb5b Sync OpenBSD patchset 294:
Add a choose-client command and extend choose-{session,window} to accept a
template. After a choice is made, %% (or %1) in the template is replaced by the
name of the session, window or client suitable for -t and the result executed
as a command. So, for example, "choose-window "killw -t '%%'"" will kill the
selected window.

The defaults if no template is given are (as now) select-window for
choose-window, switch-client for choose-session, and detach-client for
choose-client (now bound to D).
2009-08-25 13:53:39 +00:00
Tiago Cunha
c1653ff654 Sync OpenBSD patchset 293:
gcc2 doesn't understand attributes on function pointers.
2009-08-25 13:11:24 +00:00
Nicholas Marriott
22b2b7c6c5 Done. 2009-08-25 12:24:45 +00:00
Tiago Cunha
d5bc78d98b Sync OpenBSD patchset 292:
Add some other obvious variables to update-environment (WINDOWID SSH_ASKPASS
SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION) so they are updated in the session
environment on new/attach.
2009-08-24 16:35:24 +00:00
Tiago Cunha
a3799e0350 Sync OpenBSD patchset 291:
Some code tidying.
2009-08-24 16:31:26 +00:00
Tiago Cunha
35b926c445 Sync OpenBSD patchset 290:
When using source-file, run the commands in the context of the source-file
command rather than with no context. This makes things like attach work from a
file.
2009-08-24 16:27:03 +00:00
Tiago Cunha
2e2e762743 Sync OpenBSD patchset 289:
The cursession member in struct cmd_ctx is always either curclient->session or
NULL when curclient is also NULL, so just eliminate it.
2009-08-24 16:24:18 +00:00
Nicholas Marriott
266c13df18 Check the return value of strunvis against -1 not NULL. 2009-08-23 11:50:39 +00:00
Tiago Cunha
633e74ef80 Sync OpenBSD patchset 287:
Emulate dch/dch1 if missing by redrawing the entire line.
2009-08-21 21:15:00 +00:00
Tiago Cunha
1fa8a8f4a6 Sync OpenBSD patchset 285:
Ugh, committed the wrong version of this change and got both solutions rather
than just the second. Remove unused assignment.
2009-08-21 21:13:20 +00:00
Tiago Cunha
d07d18258b Sync OpenBSD patchset 284:
When moving up or down in copy mode, save the cursor position and size of the
last line with content (width != 0) and use it to determine if the cursor
should be at the end of the line. Fixes problem of the cursor always jumping to
the end of the line when scrolling past a blank line.
2009-08-21 21:12:07 +00:00
Tiago Cunha
a004fc3592 Sync OpenBSD patchset 283:
Fix grid_expand_line so it actually works when the required size is bigger than
2 * the current size.
2009-08-21 21:10:37 +00:00
Tiago Cunha
4b883524d8 Sync OpenBSD patchset 282:
A few trivial optimisations: no need to check for zero size if calling
buffer_ensure in buffer.c; expand grid lines by a greater increase than one
each time; and don't read UTF-8 data unless it actually needs to be checked
when overwriting a cell.
2009-08-21 21:09:13 +00:00
Tiago Cunha
15556ad0d6 Sync OpenBSD patchset 281:
Nuke unused variable.
2009-08-21 21:07:20 +00:00
Nicholas Marriott
27c5df22cf Move reading termios settings to before tty_open alters them, and expand the
comment.
2009-08-21 11:38:09 +00:00
Nicholas Marriott
03f4ab4bd5 Done. 2009-08-21 10:57:21 +00:00
Nicholas Marriott
f1c982608f VTIME and VMIN are only necessary in noncanonical mode, so Solaris reuses the
VEOF and VEOL indexes for them. ICANON is set by default, so don't bother to
set VTIME and VMIN.
2009-08-20 18:35:53 +00:00
Nicholas Marriott
c18e027ad5 Need this rubbish on Solaris for CMESG*. 2009-08-20 13:35:59 +00:00
Nicholas Marriott
dd9dd142c9 Add $Id$, nuke queue.h. 2009-08-20 12:54:08 +00:00
Nicholas Marriott
2f517111ef Solaris has no u_int32_t etc. 2009-08-20 12:49:18 +00:00
Nicholas Marriott
9311e4255e Didn't mean to commit this. 2009-08-20 12:39:21 +00:00
Nicholas Marriott
61c7bfc128 Also undef CTRL. 2009-08-20 12:38:37 +00:00
Nicholas Marriott
14eb6df45e Solaris defines some of these in termios.h so #ifndef them. 2009-08-20 12:27:58 +00:00
Nicholas Marriott
698e003fcd Solaris has no bzero(). 2009-08-20 12:25:17 +00:00
Tiago Cunha
cc2c061289 Sync OpenBSD patchset 280:
Handle the device attributes (DA) escape sequence.
2009-08-20 11:54:58 +00:00
Tiago Cunha
9d33b3f72a Sync OpenBSD patchset 279:
tweak previous;
2009-08-20 11:53:27 +00:00
Tiago Cunha
0027aa3d1e Sync OpenBSD patchset 278:
Don't read beyond the edge of the screen when searching (dies with debug
enabled).
2009-08-20 11:52:39 +00:00
Tiago Cunha
1292540bb5 Sync OpenBSD patchset 276:
Extend command-prompt with a -p option which is a comma-separated list of one
or more prompts to present in order.

The responses to the prompt are replaced in the template string: %% are
replaced in order, so the first prompt replaces the first %%, the second
replaces the second, and so on. In addition, %1 up to %9 are replaced with the
responses to the first the ninth prompts

The default template is "%1" so the response to the first prompt is processed
as a command.

Note that this changes the behaviour for %% so if there is only one prompt,
only the first %% will be replaced. Templates such as "neww -n '%%' 'ssh %%'"
should be changed to "neww -n '%1' 'ssh %1'".

From Tiago Cunha.
2009-08-20 11:51:20 +00:00
Tiago Cunha
4631c07483 Sync OpenBSD patchset 275:
Instead of just checking for an empty buffer, which may not be the case if
there is unconsumed data, save the previous size and use it instead. This means
that activity monitoring should work in this (unlikely) event.

Also remove a debugging statement that no longer seems necessary.
2009-08-20 11:48:01 +00:00
Tiago Cunha
d895d4a9f0 Sync OpenBSD patchset 274:
Whoops, getting the comparison the right way round is usually recommended.
2009-08-20 11:45:37 +00:00
Tiago Cunha
d3da62d53a Sync OpenBSD patchset 273:
Move another expensive options test to after a cheaper timer check/update.
2009-08-20 11:44:18 +00:00
Tiago Cunha
b644b17599 Sync OpenBSD patchset 272:
options_get_number() is relatively expensive and a check for dead panes happens
a lot more often than actually finding one, so instead of getting the option
for every check, get it for every dead window found.
2009-08-20 11:40:15 +00:00
Tiago Cunha
36475f80e9 Sync OpenBSD patchset 271:
Now that pane targets (-t) are supported, switch some commands to use them
where it makes sense: clock-mode, copy-mode, scroll-mode, send-keys,
send-prefix.
2009-08-20 11:37:46 +00:00
Tiago Cunha
52b02850ca Sync OpenBSD patchset 270:
Tag a few missed printf-like functions and fix a missing "%s".
2009-08-20 11:35:16 +00:00
Tiago Cunha
7ca3d7ac8e Do not include vis.h directly, since it's OS-dependent, due to OpenBSD
patchsets 268, and 269.
2009-08-20 11:33:13 +00:00
Tiago Cunha
3756fce553 Sync OpenBSD patchset 269:
Pass show-buffer output through vis(3) as well, and wrap it to the edge of the
terminal when used from the command line.
2009-08-20 11:30:24 +00:00
Tiago Cunha
9386f640a5 Sync OpenBSD patchset 268:
Change list-buffers to run the preview of the buffer through vis(1).
2009-08-20 11:28:05 +00:00
Tiago Cunha
bcfb4f2a07 Sync OpenBSD patchset 267:
Use the full screen width when printing output rather than one less.
2009-08-20 11:24:33 +00:00
Tiago Cunha
aa7c0f1ce8 Sync OpenBSD patchset 266:
Nuke unnecessary assignment.
2009-08-20 11:23:36 +00:00
Tiago Cunha
2a5f08c15a Sync OpenBSD patchset 265:
Add a "delete line" key when editing in the status line or the search up/down
prompt. C-u with emacs keys, d with vi.
2009-08-20 11:22:48 +00:00
Tiago Cunha
70fc085862 Sync OpenBSD patchset 264:
Add (naive) searching and goto line in copy mode. Searching is C-r and C-s with
emacs keys, / and ? with vi; n repeats the search again with either key
set. All searching wraps the top/bottom. Goto line is g for both emacs and vi.

The search prompts don't have full line editing, just simple append and delete
characters.

Also sort the mode keys list in tmux.1.
2009-08-20 11:20:24 +00:00
Nicholas Marriott
09cc530299 Solaris and AIX have no ttydefaults.h. 2009-08-20 05:34:58 +00:00
Nicholas Marriott
966818c23d Call tcsetattr(). Not tested. 2009-08-19 16:06:45 +00:00
Nicholas Marriott
7c9f827bfe In yet another triumph of stupidity over common sense, the glibc
sys/ttydefaults.h is just a copy of the file from *BSD, taking no account of
the fact that their OWN termios.h uses entirely different indexes into the
array.

I know ttydefaults.h is not meant to be portable, but you'd think it would be
obvious to anyone that no file is better than a broken one...
2009-08-19 15:57:54 +00:00
Nicholas Marriott
2a300c6661 Use cfsetispeed/cfsetospeed to set termios speed members. 2009-08-19 14:32:49 +00:00
Nicholas Marriott
53570b1505 Make this match OpenBSD. 2009-08-19 09:28:10 +00:00
Nicholas Marriott
11f0f812c5 Didn't mean to commit this stuff. 2009-08-19 09:04:48 +00:00
Nicholas Marriott
620402a833 This is a better fix for OS X stupidity. 2009-08-19 09:00:06 +00:00
Nicholas Marriott
3f7e2589cd OS X stupid poll fix. 2009-08-19 08:36:45 +00:00
Nicholas Marriott
ed26a1d3bb Update. 2009-08-18 16:21:25 +00:00
Nicholas Marriott
ae1debbc92 Example from Han Boetes. 2009-08-16 21:55:30 +00:00
Tiago Cunha
622e018570 vis(3) compat files were removed prematurely from {DragonFly,Free,Net}BSD. Add
them back, per SourceForge bug #2838408.
2009-08-16 19:48:17 +00:00
Tiago Cunha
a2a8518f74 Sync OpenBSD patchset 263:
Reset attributes as well as scroll region before poll(2) and add a big comment
explaining why.
2009-08-16 19:33:49 +00:00
Tiago Cunha
7182f6d799 Sync OpenBSD patchset 262:
Send SGR0 when initialising the screen. Fixes problems on terminals with BCE
(like putty) if the background colours is non-default when tmux starts. May
also fix problems when resuming a suspended tmux.
2009-08-16 19:31:37 +00:00
Tiago Cunha
646d6a929c Sync OpenBSD patchset 261:
Switch the prompt code to return an empty string when the user enters no
response and reserve NULL for an explicit cancel. Change all callbacks to treat
them the same so no functional change.

Also add cancel key bindings to emacs mode which were missing.
2009-08-16 19:29:24 +00:00
Tiago Cunha
6f9a2ee50a Sync OpenBSD patchset 260:
vi(1)-style half page scroll in copy and scroll modes. Move the vi full page
scroll key to C-b instead of C-u and use C-u/C-d for half page scrolling with
vi keys. In emacs mode, half page scrolling is bound to M-Up and M-Down.

Suggested by merdely (about a year ago :-)).
2009-08-16 19:26:49 +00:00
Tiago Cunha
98e9e09588 Sync OpenBSD patchset 259:
Scroll by two less than the number of lines in the screen, like emacs, rather
than by the entire screen, to make it easier to pull things out from under the
line indicator. Suggested by claudio.
2009-08-16 19:23:07 +00:00
Tiago Cunha
9541471f87 Sync OpenBSD patchset 258:
Disable mode-mouse (mouse in copy/choice mode) by default as it isn't very
useful at the moment and causes confusion.
2009-08-16 19:20:37 +00:00
Tiago Cunha
c1fee8793d Update. 2009-08-16 19:18:10 +00:00
Tiago Cunha
e61ee94e26 Sync OpenBSD patchset 257:
Add a base-index session option to specify the first index checked when looking
for an index for a new window.
2009-08-16 19:16:27 +00:00
Tiago Cunha
9116905b24 Sync OpenBSD patchset 256:
Allowing copy mode to scroll left and right is annoying, so limit it to the
real screen width. To indicate the cursor is at the end of the line rather than
the cell before, put a '$' in the last cell.

Also clear the selection when the terminal is resized to avoid tmux getting
confused.
2009-08-16 19:12:07 +00:00
Tiago Cunha
64950f4524 Sync OpenBSD patchset 255:
Rather than telling the client to exit in the function when creating a new
session detached, let the caller do it. Allows "tmux new -d \; attach" to work.
2009-08-16 19:07:40 +00:00
Tiago Cunha
8973af82c5 Include unistd.h due to OpenBSD patchset 254. At least on Linux, that's where
_POSIX_VDISABLE is defined.
2009-08-16 19:04:05 +00:00
Tiago Cunha
f415d43c3b Sync OpenBSD patchset 254:
When creating a new session from the command-line where there is an external
terminal, copy the termios(4) special characters and use them for new windows
created in the new session. Suggested by Theo.
2009-08-16 18:59:12 +00:00
Nicholas Marriott
8f9858ba2f Solaris has no strsep(3). 2009-08-16 16:15:53 +00:00
Tiago Cunha
ba42910595 Sync OpenBSD patchset 253:
Redraw the screen after resizing.
2009-08-14 21:33:42 +00:00
Tiago Cunha
78c789e1cb Sync OpenBSD patchset 252:
It was originally intended that scroll mode would show content that was
currently off-screen due to resize, but somewhere along the way this got
lost. Restore this behaviour to scroll mode by fixing screen_write_copy to read
up to the saved line length rather than the current screen width. Copy mode
remains unaltered for now.
2009-08-14 21:32:38 +00:00
Tiago Cunha
b5059bc8a4 Sync OpenBSD patchset 251:
If the client passes zero for the window size in the identify message (which it
can, for example on serial terminals), reset it to 80x25, same as for resize
messages. Problem reported by kettenis@.
2009-08-14 21:31:20 +00:00
Tiago Cunha
05fe69eb92 Sync OpenBSD patchset 250:
A tty context must not be modified as it may be reused to update multiple
clients, so make it const.

Also fix an actual modification which caused a hang when a session was
connected to multiple terminals at least one of which was missing ich/ich1.
2009-08-14 21:30:24 +00:00
Tiago Cunha
06b3f49c49 Sync OpenBSD patchset 249:
When started as the shell, __progname contains a leading -, so hardcode "tmux"
for socket path and log files, and strip it when working out the shell.
2009-08-14 21:28:00 +00:00
Tiago Cunha
1063e5d0e4 Sync OpenBSD patchset 248:
imsg closes the fd after sending, so dup() STDIN_FILENO before passing it to
the parent, otherwise TIOCGWINSZ will fail when the window is resized (that
could actually be moved into the server but this is more future-proof and
avoids breaking the protocol).
2009-08-14 21:26:07 +00:00
Tiago Cunha
7f77c395e3 Sync OpenBSD patchset 247:
Initialise log_fd to -1, prevents spurious disconnection of the client when it
ends up as fd 0 (likely if the server is started with "tmux start").

Also add some extra debugging messages to server.c.
2009-08-14 21:24:46 +00:00
Tiago Cunha
e2a18894b3 Sync OpenBSD patchset 246:
Have the client pass its stdin fd to the server when identifying itself and
have the server use that rather than reopening the tty. If the fd isn't given,
use the old behaviour (so no need for a version change).

This allows tmux to be used as the shell, so also change so that when working
out the command to execute if default-command is empty (the default), tmux will
try not execute itself.
2009-08-14 21:23:20 +00:00
Tiago Cunha
0714e41148 Sync OpenBSD patchset 245:
Add a TTY_OPENED flag and tidy a little.
2009-08-14 21:20:01 +00:00
Tiago Cunha
5cc971facd Sync OpenBSD patchset 244:
Drop the no_stop argument to tty_close and tty_free in favour of a flag in the
tty struct.
2009-08-14 21:17:54 +00:00
Tiago Cunha
b402cef338 Adjust imsg changes to the portable version due to OpenBSD patchset 243. 2009-08-14 21:13:48 +00:00
Tiago Cunha
a9b6bfdddd Sync OpenBSD patchset 243:
Switch tmux to use imsg. This is the last major change to make the
client-server protocol more resilient and make the protocol versioning work
properly. In future, the only things requiring a protocol version bump will be
changes in the message structs, and (when both client and server have this
change) mixing different versions should nicely report an error message.

As a side effect this also makes the code tidier, fixes a problem with the way
errors reported during server startup were handled, and supports fd passing
(which will be used in future).

Looked over by eric@, thanks.

Please note that mixing a client with this change with an older server or vice
versa may cause tmux to crash or hang - tmux should be completely exited before
upgrading.
2009-08-14 21:04:04 +00:00
Nicholas Marriott
a604dfbb97 +. 2009-08-13 22:39:22 +00:00
Nicholas Marriott
e9d170176d Add and remove some bits. 2009-08-13 22:36:20 +00:00
Nicholas Marriott
304296972b Sync from OpenBSD:
Add flags for 1+2 and 2 arguments to the generic target code, use it for
cmd-set-environment/option/window-option and remove the generic options
parsing.
2009-08-11 14:42:59 +00:00
Nicholas Marriott
d0eae2cbfd +. 2009-08-11 10:09:32 +00:00
Nicholas Marriott
4d90ce7b40 Update. 2009-08-11 10:06:27 +00:00
Tiago Cunha
48ede1a00a Sync OpenBSD patchset 241:
No arguments are the same as new-session and this requires the environment to
be sent, so set that flag too when argc == 0.
2009-08-10 21:43:34 +00:00
Tiago Cunha
c261ae32d2 Sync OpenBSD patchset 240:
Reset the attributes after drawing all or part of the screen, and reset the
region before poll(2). This reduces (but does not eliminate) the chance of the
attributes not being normal if tmux is disconnected without warning (ssh ~.,
reboot from inside, etc).
2009-08-10 21:41:35 +00:00
Tiago Cunha
e8ea3ccd58 Sync OpenBSD patchset 239:
Use the right source and destination lines in grid_duplicate_lines.
2009-08-10 21:40:21 +00:00
Tiago Cunha
7bcd7c2752 Sync OpenBSD patchset 238:
some minor tweaks; ok nicm
2009-08-10 21:39:15 +00:00
Nicholas Marriott
7dbabe84e4 Missing options are not illegal. 2009-08-09 18:35:38 +00:00
Tiago Cunha
3dadb349eb Sync OpenBSD patchset 237:
zap trailing whitespace;
2009-08-09 18:02:36 +00:00
Tiago Cunha
e43ce15736 Sync OpenBSD patchset 236:
Minor language tweaks, change which key bindings are summarised.
2009-08-09 18:02:02 +00:00
Tiago Cunha
6297285527 Nuke dead variable here as well, in accordance to OpenBSD patchset 235. 2009-08-09 18:00:45 +00:00
Tiago Cunha
2c863b9f2c Sync OpenBSD patchset 235:
Nuke a dead variable found with clang and an unused declaration with lint.
2009-08-09 17:57:39 +00:00
Tiago Cunha
221ce5afb3 Sync OpenBSD patchset 234:
Move the key bindings section to near the start, mention attach/detach in the
first section, and another couple of tweaks. Based on a diff from Theo.
2009-08-09 17:55:59 +00:00
Tiago Cunha
1297c39a31 Sync OpenBSD patchset 233:
Don't leak in the (rare) case of an invalid command at the end of a file not
terminated by a \n.
2009-08-09 17:53:50 +00:00
Tiago Cunha
4c944910fa Sync OpenBSD patchset 232:
Use a temporary variable for strdup of const char *.
2009-08-09 17:52:54 +00:00
Tiago Cunha
deac1fc188 Update. 2009-08-09 17:51:19 +00:00
Tiago Cunha
29b1b2fb5e Sync OpenBSD patchset 231:
Infrastructure and commands to manage the environment for processes started
within tmux.

There is a global environment, copied from the external environment when the
server is started and each session has an (initially empty) session
environment which overrides it.

New commands set-environment and show-environment manipulate or display the
environments.

A new session option, update-environment, is a space-separated list of
variables which are updated from the external environment into the session
environment every time a new session is created - the default is DISPLAY.
2009-08-09 17:48:55 +00:00
Tiago Cunha
af3db9a4fe Sync OpenBSD patchset 230:
Tidy function a little by using a temporary variable.
2009-08-09 17:43:00 +00:00
Tiago Cunha
a26817d604 Update. 2009-08-09 17:41:46 +00:00
Tiago Cunha
167a8c9edc Sync OpenBSD patchset 229:
Options to set the colours and attributes for status-left/-right. From Thomas
Adam, thanks.
2009-08-09 17:40:17 +00:00
Tiago Cunha
97eb537f38 Sync OpenBSD patchset 227:
Add a flags member to the grid_line struct and use it to differentiate lines
wrapped at the screen edge from those terminated by a newline. Then use this
when copying to combine wrapped lines together into one.
2009-08-09 17:32:06 +00:00
Tiago Cunha
37b0bcd7c1 Sync OpenBSD patchset 226:
Change the way the grid is stored, previously it was:

- a two-dimensional array of cells;
- a two-dimensional array of utf8 data;
- an array of line lengths.

Now it is a single array of a new struct grid_line each of which represents a
line and contains the length and an array of cells and an array of utf8 data.

This will make it easier to add additional per-line members, such as flags.
2009-08-09 17:28:24 +00:00
Tiago Cunha
5b56ea1816 Sync OpenBSD patchset 225:
If there is an error in the configuration file, don't just exit(1) as this can
cause the client to hang. Instead, send the error message, then mark the client
as bad and start a normal shutdown so the server exits once the error is
written.

This also allows some code duplicating daemon(3) to be trimmed and logging to
begin earlier.

Prompted by Theo noticing the behaviour on error wasn't documented.
2009-08-09 17:19:18 +00:00
Tiago Cunha
602aae7839 Sync OpenBSD patchset 224:
Move introduction section up into description. From jmc.
2009-08-09 16:59:35 +00:00
Tiago Cunha
05eb4ece44 Sync OpenBSD patchset 223:
Using the alternative screen (smcup/rmcup) should also preserve the current
colours and attributes. Found thanks to a report from Taylor Venable.

While here also nuke a couple of extra blank lines.
2009-08-09 16:57:49 +00:00
Tiago Cunha
5840c3e13a Sync OpenBSD patchset 222:
tweak INTRODUCTION; from nicm and myself (jmc)
2009-08-09 16:54:46 +00:00
Tiago Cunha
cd5294dfb4 Sync OpenBSD patchset 221:
Clear the codes array earlier as tty_term_free could be called on error.
2009-08-09 16:52:06 +00:00
Tiago Cunha
88b83be07b Sync OpenBSD patchset 220:
If colours are not supported by the terminal, try to emulate a coloured
background by setting or clearing the reverse attribute.

This makes a few applications which don't use the reverse attribute themselves
a little happier, and allows the status, message and mode options to have
default attributes and fg/bg options that work as expected when set as reverse.
2009-08-09 16:50:57 +00:00
Tiago Cunha
65a28912eb Sync OpenBSD patchset 219:
Add a -a flag to set-option and set-window-option to append to an existing
string value, useful for terminal-overrides.
2009-08-09 16:48:34 +00:00
Tiago Cunha
d8a2ceea43 Sync OpenBSD patchset 217:
Show the bell/activity/current status and the window title in the choice list.
2009-08-09 16:41:17 +00:00
Tiago Cunha
c32ca6a8e6 Sync OpenBSD patchset 216:
Check for "UTF8" as well as "UTF-8" in LANG etc as it seems this may also
appear.
2009-08-09 16:39:40 +00:00
Tiago Cunha
c9f55c1063 Make similar (untested) changes to the OS-dependent code for FreeBSD, and
NetBSD in accordance to OpenBSD patchset 214.
2009-08-09 16:37:05 +00:00
Tiago Cunha
1127a290f4 Sync OpenBSD patchset 214:
Split the comparison into a function to make this code smaller and more
understandable.
2009-08-09 16:08:12 +00:00
Tiago Cunha
bd5cf2e809 Update. 2009-08-09 15:58:09 +00:00
Tiago Cunha
9002e60adf Sync OpenBSD patchset 213:
Don't try to free old string values (and crash) when they are overridden unless
they were actually found in the source terminal description. Reported by jmc.
2009-08-09 15:57:13 +00:00
Tiago Cunha
bd2fe4ce9b Make it build on the remaining operating systems, due to the changes
introduced on OpenBSD patchset 211.
2009-08-09 15:53:02 +00:00
Tiago Cunha
e6d5633671 DragonFlyBSD, FreeBSD, and NetBSD do not need vis.c. 2009-08-09 15:48:03 +00:00
Tiago Cunha
e098f7b285 Add unvis(3) compat stuff. 2009-08-09 15:39:41 +00:00
Tiago Cunha
3deb17e841 Do not include vis.h directly, since it's OS-dependent. 2009-08-09 15:29:54 +00:00
Tiago Cunha
15f6a41a75 Sync OpenBSD patchset 211:
Add a terminal-overrides session option allowing individual terminfo(5) entries
to be overridden. The 88col/256col checks are now moved into the default
setting and out of the code.

Also remove a couple of old workarounds for xterm and rxvt which are no longer
necessary (tmux can emulate them if missing).
2009-08-09 15:26:24 +00:00
Tiago Cunha
75b6736cf4 Sync OpenBSD patchset 210:
Fix checking of setupterm(3) error codes. While there include the
name of the terminal type causing the error where relevant. ok nicm@.
2009-08-09 12:06:25 +00:00
Nicholas Marriott
80196c9abc Fix typo and add ref to infocmp. 2009-08-08 20:46:26 +00:00
Nicholas Marriott
becdf220fd Clarify 256 colours entries from Chris Jones, tweaked by me. 2009-08-08 20:42:42 +00:00
Nicholas Marriott
dcde77cd09 Update. 2009-08-08 16:03:09 +00:00
Nicholas Marriott
f03dd8d216 This file is not kept up to date and too many people are using it as-is then
finding tmux key bindings missing. Trim it down and make it clear this is an
example only.
2009-08-07 12:09:50 +00:00
Nicholas Marriott
a5d55ba16d Sync up tmux.1 from OpenBSD. 2009-08-06 19:25:44 +00:00
Nicholas Marriott
2936f4f32c tmux no longers sends init strings so this is no longer relevant. 2009-08-06 12:22:50 +00:00
Nicholas Marriott
e2686d8819 +IRC channel. 2009-08-05 16:39:28 +00:00
Nicholas Marriott
b2606c0421 Correct usage of termcap. 2009-08-05 16:29:50 +00:00
Nicholas Marriott
e3e0d70c0e +PuTTY ACS from Mike Putnam. 2009-08-05 14:56:58 +00:00
Nicholas Marriott
f42a0475e4 Tweak FAQ to mention default-terminal. 2009-08-05 14:42:08 +00:00
Tiago Cunha
a834d037bc Sync OpenBSD patchset 209:
Pass the ACS border characters through tty_get_acs so they appear correctly on
terminals which don't use the standard set.
2009-07-31 20:35:21 +00:00
Tiago Cunha
cccd072ed1 Sync OpenBSD patchset 208:
Don't leak when rollling buffers off when the paste buffer limit is reached.
2009-07-31 20:33:49 +00:00
Nicholas Marriott
5f0e688b50 Add some lines. 2009-07-31 10:58:51 +00:00
Nicholas Marriott
ec8930c144 Part of last commit, remove -lcurses. 2009-07-31 10:45:22 +00:00
Nicholas Marriott
3e46bcec93 On SUSE Linux compatibility is something that only happens to other people, so
on Linux use -lncurses instead of -lcurses.

Also use -lncurses on NetBSD because they are only now realising that
supporting the 20-year-old terminfo API in their libcurses might be nice, and
so far none of the releases do.
2009-07-31 10:44:03 +00:00
Nicholas Marriott
5d13704e04 Some Linuxes/gcc versions hide LLONG_MAX/MIN unless the compiler is told to use
C99, so use -std=c99 on Linux.
2009-07-31 10:30:40 +00:00
Nicholas Marriott
52f8578984 Some stuff that is done. 2009-07-30 21:55:16 +00:00
Tiago Cunha
09c6432854 Sync OpenBSD patchset 207:
Plug some memory leaks.
2009-07-30 21:14:04 +00:00
Tiago Cunha
796bfbd7af Update. 2009-07-30 21:11:10 +00:00
Tiago Cunha
56dd5dfff4 Sync OpenBSD patchset 206:
Don't babysit people and let them try to load /dev/zero or (more useful)
/dev/null if they want.
2009-07-30 21:07:23 +00:00
Tiago Cunha
3eb77bf53f Sync OpenBSD patchset 205:
Remove some dead code found by clang.
2009-07-30 21:04:40 +00:00
Tiago Cunha
89826983eb Sync OpenBSD patchset 204:
tweak previous;
2009-07-30 21:02:35 +00:00
Tiago Cunha
697051d1fd Sync OpenBSD patchset 203:
Similar changes for server_msg_dispatch: use a switch instead of a lookup
table and merge smaller functions inline.
2009-07-30 21:01:01 +00:00
Tiago Cunha
67266dc25c Sync OpenBSD patchset 202:
There aren't many client message types or code to handle them so get rid of
the lookup table and use a switch, merge the tiny handler functions into it,
and move the whole lot to client.c.

Also change client_msg_dispatch to consume as many messages as possible and
move the call to it to the right place so it checks for signals afterwards.

Prompted by suggestions from eric@.
2009-07-30 20:57:39 +00:00
Tiago Cunha
817e93ac94 Sync OpenBSD patchset 201:
Tell the server when the client gets SIGTERM so it can clean up the terminal
properly, rather than just exiting.
2009-07-30 20:50:10 +00:00
Tiago Cunha
1650b8552f Sync OpenBSD patchset 200:
Merge pane number into the target specification for pane commands. Instead of
using -p index, a target pane is now addressed with the normal -t window form
but suffixed with a period and a pane index, for example :0.2 or
mysess:mywin.1. An unadorned number such as -t 1 is tried as a pane index in
the current window, if that fails the same rules are followed as for a target
window and the current pane in that window used.

As a side-effect this now means that swap-pane can swap panes between
different windows.

Note that this changes the syntax of the break-pane, clear-history, kill-pane,
resize-pane, select-pane and swap-pane commands.
2009-07-30 20:45:20 +00:00
Tiago Cunha
ec1396c9ee Sync OpenBSD patchset 199:
new sentence, new line;
2009-07-30 20:33:29 +00:00
Tiago Cunha
ec3dba01b2 Sync OpenBSD patchset 198:
Add a mode-mouse option to prevent tmux taking over the mouse in choice or
copy modes.
2009-07-30 20:32:05 +00:00
Tiago Cunha
8ce1f0b047 Sync OpenBSD patchset 197:
Add an additional heuristic to work out the current session when run from the
command line. The name of all slave ptys in the server is known, so if the
client was run on a tty, look for any sessions containing that tty and use the
most recently created.

This is more reliable than looking at $TMUX if windows have been moved or
linked between sessions.
2009-07-30 20:26:20 +00:00
Tiago Cunha
6fbfcfc0d7 Sync OpenBSD patchset 196:
Rename struct hdrtype to msgtype which is a better name and can be used even
when struct hdr disappears.
2009-07-30 20:21:55 +00:00
Tiago Cunha
5a9b7b230c Sync OpenBSD patchset 195:
Taking account of the "s, 22 not 24 is the maximum length of #T in
status-right to prevent the date being cut off.
2009-07-30 20:17:25 +00:00
Tiago Cunha
522fc94d12 Sync OpenBSD patchset 194:
Final pieces of mode key rebinding: bind-key and unbind-key now accept a -t
argument to modify a table.
2009-07-28 23:19:06 +00:00
Tiago Cunha
deaba44835 Sync OpenBSD patchset 193:
Accept and print "Enter" and "Escape" for keys rather than C-m and C-[.
2009-07-28 23:13:00 +00:00
Tiago Cunha
de7483a114 Sync OpenBSD patchset 192:
Next step towards customisable mode keys: build each default table of keys
into a named tree on start and use that for lookups. Also add command to string
translation tables and modify list-keys to show the mode key bindings (new
-t argument).
2009-07-28 23:11:18 +00:00
Tiago Cunha
d9dcc5ed44 Sync OpenBSD patchset 191:
If select-layout is not given an argument, reapply the last layout used in the
window, if any.
2009-07-28 23:04:29 +00:00
Tiago Cunha
1c73e75982 Sync OpenBSD patchset 190:
Remove an unused entry in the mode keys command enum and rename
MODEKEYCOPY_QUIT to _CANCEL to match the others.
2009-07-28 22:58:20 +00:00
Tiago Cunha
920b9c5872 Sync OpenBSD patchset 189:
Change mode key bindings from big switches into a set of tables. Rather than
lumping them all together, split editing keys from those used in choice/more
mode and those for copy/scroll mode.

Tidier and clearer, and the first step towards customisable mode keys.
2009-07-28 22:55:59 +00:00
Tiago Cunha
1880b83c37 Sync OpenBSD patchset 188:
Get rid of empty mode_key_free function.
2009-07-28 22:49:26 +00:00
Tiago Cunha
46cb0de347 Sync OpenBSD patchset 187:
Add a key to delete to end of line at the prompt (^K in emacs mode, C/D in
vi).

From Kalle Olavi Niemitalo.
2009-07-28 22:44:38 +00:00
Tiago Cunha
7562781c9d Sync OpenBSD patchset 186:
Draw UTF-8 characters under the selection correctly.
2009-07-28 22:41:38 +00:00
Tiago Cunha
2a146852ef Sync OpenBSD patchset 185:
Change previous-word behavior to move to the beginning of the word (matches
emacs and vi). From Kalle Olavi Niemitalo.
2009-07-28 22:39:29 +00:00
Tiago Cunha
361801aaaa Sync OpenBSD patchset 184:
Detect backspace by looking at termios VERASE and translate it into \177
(which matches screen's behaviour if not its termcap/terminfo entry). The
terminfo kbs cap is often wrong or missing so it can't be used, and just
assuming \177 may be wrong.
2009-07-28 22:37:02 +00:00
Tiago Cunha
2aa4d47312 Sync OpenBSD patchset 183:
Calculate the space available for the prompt buffer and the cursor position
correctly, and make it work when the screen is not wide enough.

Noticed by Kalle Olavi Niemitalo.
2009-07-28 22:32:15 +00:00
Tiago Cunha
2dda197980 Make similar changes to the OS-dependent code for FreeBSD, and NetBSD in
accordance to OpenBSD patchset 182.
2009-07-28 22:28:11 +00:00
Tiago Cunha
6043d9cf89 Sync OpenBSD patchset 182:
Go to the next if the current best process is replaced, don't keep comparing
it with itself. Also fix process name comparison.
2009-07-28 22:26:13 +00:00
Tiago Cunha
a3fc9dee32 Add PASS_MAX for glibc. 2009-07-28 22:17:10 +00:00
Tiago Cunha
d637cb33da Sync OpenBSD patchset 181:
Make all messages sent between the client and server fixed size.

This is the first of two changes to make the protocol more resilient and less
sensitive to other changes in the code, particularly with commands. The client
now packs argv into a buffer and sends it to the server for parsing, rather
than doing it itself and sending the parsed command data.

As a side-effect this also removes a lot of now-unused command marshalling
code.

Mixing a server without this change and a client with or vice versa will cause
tmux to hang or crash, please ensure that tmux is entirely killed before
upgrading.
2009-07-28 22:12:16 +00:00
Nicholas Marriott
f5c0695605 This stuff is done. 2009-07-28 18:51:10 +00:00
Nicholas Marriott
21130b0c49 Add a couple of items, and wrap lines. 2009-07-26 15:58:40 +00:00
Tiago Cunha
a5ad186547 Sync OpenBSD patchset 180:
Set the active pane when respawning a window - fixes problems when respawning
a window with multiple panes.
2009-07-25 09:04:54 +00:00
Tiago Cunha
5e7a48a865 Sync OpenBSD patchset 179:
Use the full range of ACS line drawing characters to draw pane borders,
including intersections.
2009-07-25 09:03:33 +00:00
Tiago Cunha
2386fa2355 Sync OpenBSD patchset 178:
cmd_find_index should return -2 on error.
2009-07-25 08:59:38 +00:00
Tiago Cunha
723f363c07 Sync OpenBSD patchset 177:
Simplify screen redrawing by drawing the border and background together rather
than border separately, and consolidating all the drawing characters into one
string.
2009-07-25 08:58:19 +00:00
Tiago Cunha
a98dbb67b9 Sync OpenBSD patchset 176:
Accept lowercase c- and m- prefix as well as C- and M-.
2009-07-25 08:53:48 +00:00
Tiago Cunha
28cf7dc39e Sync OpenBSD patchset 175:
Permit commands to be bound to key presses without the prefix key first. The
new -n flag to bind-key and unbind-key sets or removes these bindings, and
list-key shows them in []s.
2009-07-25 08:52:04 +00:00
Tiago Cunha
744ccb7cc9 Sync OpenBSD patchset 174:
up-pane and down-pane no longer auto-repeat; update the description of
repeat-time accordingly. ok nicm@

if you prefer old behaviour;

bind -r Up up-pane
bind -r Down down-pane
2009-07-25 08:39:39 +00:00
Nicholas Marriott
db584544f4 Add some more bits. 2009-07-25 00:12:24 +00:00
Nicholas Marriott
f4718dcdf2 +another couple of items. 2009-07-25 00:00:33 +00:00
Nicholas Marriott
4ec1b5d4e2 +. 2009-07-24 22:59:06 +00:00
Nicholas Marriott
6e0626d3af Screenshot with more ACS love. 2009-07-24 19:30:51 +00:00
Nicholas Marriott
dd51dd14af Add. 2009-07-24 19:30:05 +00:00
Tiago Cunha
7cd412dc57 Sync OpenBSD patchset 173:
None of the server message functions return anything but 0, so make them all
void.

Also remove a leftover variable in client.c.
2009-07-23 23:47:23 +00:00
Tiago Cunha
1870b96578 Sync OpenBSD patchset 172:
Tidy client message return slightly: convert flags into an enum, and merge
error string into struct client_ctx as well.
2009-07-23 23:42:59 +00:00
Tiago Cunha
2e4df706f6 Sync OpenBSD patchset 171:
Redraw after starting selection to correctly remove any existing selection.
2009-07-23 23:37:14 +00:00
Tiago Cunha
1141acfd4c Revert previous per OpenBSD's patchset 170. 2009-07-23 23:35:10 +00:00
Tiago Cunha
53c1b32e02 Sync OpenBSD patchset 169:
C-d is delete as well in emacs mode.
2009-07-23 23:29:53 +00:00
Tiago Cunha
f2451c1e29 Sync OpenBSD patchset 168:
Both of cmdclient and curclient CAN be NULL - if the command is executed from
the configuration file. In this case, attach-session can't do much, and
new-session should just assume -d.
2009-07-23 13:25:27 +00:00
Tiago Cunha
a551ff2b1b Sync OpenBSD patchset 167:
If there is a current session, use its default path and working directory for
the initial window when creating a new session.
2009-07-23 13:19:12 +00:00
Tiago Cunha
7174c76bf0 Sync OpenBSD patchset 166:
Pass a set of flags into client_init rather than just a start_server
variable. Only one flag now but more to come later.
2009-07-23 13:15:41 +00:00
Tiago Cunha
6708ad19c5 Sync OpenBSD patchset 165:
window_add_pane cannot fail, so remove the unused cause argument and don't
bother to check for a NULL return.
2009-07-23 13:10:38 +00:00
Tiago Cunha
fb0301f8b8 Sync OpenBSD patchset 164:
Tidy the target parsing code a bit and correct the behaviour so that as before
a string with no colon as a target window is first looked up as a window then
as a session, noted by Iain Morgan.

Also attempt to clarify the description of the target specification in the man
page.
2009-07-23 13:06:31 +00:00
Tiago Cunha
c84145751a Sync OpenBSD patchset 164:
tty_write is relatively short and the only function left in tty-write.c so
move it into tty.c.
2009-07-23 12:57:45 +00:00
Tiago Cunha
b72f9bea43 Sync OpenBSD patchset 162:
More tty code tidying: move the saved cursor/region position (from before the
screen was updated) out of struct screen and into struct tty_ctx.
2009-07-23 12:48:18 +00:00
Tiago Cunha
9c6fa90857 Sync OpenBSD patchset 160:
enum tty_cmd is only used as an index into the array of command function
pointers, so remove it and use the function pointers directly to represent
themselves.
2009-07-23 12:38:01 +00:00
Nicholas Marriott
83d1f2b480 Some more TODO list items that are done. 2009-07-22 21:10:45 +00:00
Nicholas Marriott
19aae6dbd8 Add a couple of notes so I don't forget. 2009-07-22 21:02:07 +00:00
Tiago Cunha
aa3a262caa Update. 2009-07-22 20:42:56 +00:00
Tiago Cunha
b6afa30c39 Sync OpenBSD patchset 159:
There are relatively few arguments to tty_cmd_* functions now, so tidy them up
by using a struct rather than hiding everything with varargs.
2009-07-22 18:08:56 +00:00
Tiago Cunha
75a44d856e Sync OpenBSD patchset 158:
tty_cmd_raw is only used once, for raw UTF-8 output, so rename it to
tty_cmd_utf8character and eliminate the size argument.
2009-07-22 17:58:42 +00:00
Tiago Cunha
41207e4861 Sync OpenBSD patchset 157:
Adjust field width to fit longest key when listing.
2009-07-22 17:53:27 +00:00
Tiago Cunha
acdef09e00 Sync OpenBSD patchset 156:
Remove leftover debug logging of password.
2009-07-22 17:49:09 +00:00
Tiago Cunha
d29b57f597 Sync OpenBSD patchset 155:
Make some functions which return unused values void (mostly found by lint) and
tweak a redundant expression in window_pane_set_mode.
2009-07-22 17:46:53 +00:00
Tiago Cunha
0237e1dafd Sync OpenBSD patchset 154:
Nix a few unused attributes on arguments which are no longer unused.
2009-07-22 17:38:11 +00:00
Tiago Cunha
a92993228f Change GRID_DEBUG to use log_debug2 since log_debug3 was removed. 2009-07-22 17:33:02 +00:00
Tiago Cunha
6a97901691 Sync OpenBSD patchset 153:
Remove a couple of unused functions and fix a type ("FALLTHOUGH"), found by
lint.
2009-07-22 17:31:20 +00:00
Tiago Cunha
39aa8b32b1 Restore $Id$. 2009-07-22 16:55:22 +00:00
Tiago Cunha
1bf524c1b7 Sync OpenBSD patchset 152:
__progname is not const, pointed out by deraadt.

And, as a consequence change its declaration for operating systems which
don't provide __progname as well.
2009-07-22 16:53:30 +00:00
Tiago Cunha
a734488a4b Sync OpenBSD patchset 151:
Tidy up keys: use an enum for the key codes, and remove the macros which just
wrap flag sets/clears/tests.
2009-07-22 16:24:59 +00:00
Nicholas Marriott
94e2339842 OpenSolaris ioctl(TIOCSWINSZ) appears to be broken and can return EINVAL here
despite sx, sy and fd being fine (an fcntl on the fd succeeds). No problems on
other platforms so ignore the error under #ifdef __sun__.
2009-07-22 12:42:57 +00:00
Tiago Cunha
5263b3f61e Sync OpenBSD patchset 150:
Now that #P could be in the status line, flag it for redraw when the active
pane changes.
2009-07-21 16:27:41 +00:00
Nicholas Marriott
962b9c6548 Include .depend in GNUmakefile since GNU make does not include it
automatically.

Also remove .depend from clean target and add a clean-depend target.
2009-07-21 13:51:30 +00:00
Nicholas Marriott
48c36d628a No paths.h in cmd.c; add _PATH_DEV for Solaris. 2009-07-21 13:07:50 +00:00
Nicholas Marriott
e2a80151ae Update. 2009-07-21 13:07:14 +00:00
Tiago Cunha
2572c7139b Sync OpenBSD patchset 149:
Tweak unbind-key language very slightly.
2009-07-20 17:08:48 +00:00
Tiago Cunha
e7cda4f363 Update. 2009-07-20 17:06:13 +00:00
Tiago Cunha
54c6848d75 Sync OpenBSD patchset 148:
Display the number of failed password attempts (if any) when the server is
locked. From Tom Doherty.
2009-07-20 16:07:23 +00:00
Tiago Cunha
9a07e8f372 Sync OpenBSD patchset 147:
Add a status-justify option to allow the window list in the status line to be
positioned at the left, centre, or right.
2009-07-20 16:01:07 +00:00
Tiago Cunha
e8957009c7 Sync OpenBSD patchset 146:
New options, window-status-current-{fg,bg,attr}, to set the fg, bg and
attributes with which the current window is shown in the status line. From
Johan Friis, thanks.
2009-07-20 15:57:05 +00:00
Tiago Cunha
62017452e9 Sync OpenBSD patchset 145:
Kill some dead stores and fix a null pointer deref, found by clang.
2009-07-20 15:51:32 +00:00
Tiago Cunha
16f424d25d Sync OpenBSD patchset 144:
Move the offsets as well when swapping panes.
2009-07-20 15:48:54 +00:00
Tiago Cunha
95d593dd51 Sync OpenBSD patchset 143:
tweak previous;
2009-07-20 15:46:55 +00:00
Tiago Cunha
545893df73 Sync OpenBSD patchset 142:
Each window now has a tree of layout cells associated with it. In this tree,
each node is either a horizontal or vertical cell containing a list of other
cells running from left-to-right or top-to-bottom, or a leaf cell which is
associated with a pane.

The major functional changes are:

- panes may now be split arbitrarily both horizontally (splitw -h, C-b %) and
  vertically (splitw -v, C-b ");
- panes may be resized both horizontally and vertically (resizep -L/-R/-U/-D,
  bound to C-b left/right/up/down and C-b M-left/right/up/down);
- layouts are now applied and then may be modified by resizing or splitting
  panes, rather than being fixed and reapplied when the window is resized or
  panes are added;
- manual-vertical layout is no longer necessary, and active-only layout is gone
  (but may return in future);
- the main-pane layouts now reduce the size of the main pane to fit all panes
  if possible.

Thanks to all who tested.
2009-07-20 15:42:05 +00:00
Nicholas Marriott
680f2098f1 With gcc4, turn off unnecessart pointer sign warnings. 2009-07-20 05:40:13 +00:00
Tiago Cunha
376c808b50 Add three new session options: visual-activity, visual-bell, visual-content.
If these are enabled (and the monitor-activity, bell-action and monitor-content
options are configurated appropriately), when activity, a bell, or content is
detected, a message is shown.

Also tidy up the bell/activity/content code in server.c slightly and fix a
couple of errors.
2009-07-19 14:35:56 +00:00
Nicholas Marriott
4cf6396e4c Change a couple of screenshots which had screen in them now I've got rid of
screen on that box too :-).
2009-07-19 13:52:51 +00:00
Tiago Cunha
17170f5d6e Add a -k flag to unlink-window which makes it behave the same as the old
kill-window - if a window is linked into only one session it unlinked and
destroyed.
2009-07-19 00:39:37 +00:00
Nicholas Marriott
19cb1fb592 Make it so using kill-pane to destroy the last pane in a window destroys the
window instead of being an error.
2009-07-18 11:07:14 +00:00
Nicholas Marriott
c30fbd1d8d When resizing a screen smaller in alternate screen mode, all the lines needed
could be consumed by deleting from the bottom, leaving none to be removed from
the top. In this case, don't call grid_view_delete_lines with ny of 0 as this
is incorrect and causes a bounds check to fatal error if built with -DDEBUG.
2009-07-18 11:06:35 +00:00
Nicholas Marriott
6bc9ee3420 Tidy up new-session and attach-session and change them to work from inside
tmux, switching the current client to the new or requested session.
2009-07-18 11:06:09 +00:00
Nicholas Marriott
4192449112 Remove a duplicate key binding, and turn off autorepeat for up/down as it is
kind of annoying by default.
2009-07-18 11:05:45 +00:00
Nicholas Marriott
f1efd6b4e7 If -u is specified or UTF-8 is otherwise detected when the server is started,
enable the utf8 and status-utf8 optons. While here, note in the man page that
the server is started with the first session and exits when none remain.
2009-07-18 11:05:13 +00:00
Nicholas Marriott
21cfef45d6 When resizing a screen smaller in alternate screen mode, all the lines needed
could be consumed by deleting from the bottom, leaving none to be removed from
the top. In this case, don't call grid_view_delete_lines with ny of 0 as this
is incorrect and causes a bounds check to fatal error if built with -DDEBUG.
2009-07-17 18:35:55 +00:00
Tiago Cunha
ae7dda10ce - New command display-message (alias display) to display a message in the
status line (bound to "i" by default).
- Add support for including the window index, pane index, and window name
  in status-left, or status-right.
- Bump protocol version.
2009-07-17 18:32:54 +00:00
Nicholas Marriott
646632de1d Update TODO. 2009-07-17 18:05:06 +00:00
Nicholas Marriott
770ea563ee Changed the wrong thing here. 2009-07-17 15:56:46 +00:00
Nicholas Marriott
946affe60d Stupid cvsps. 2009-07-17 12:35:01 +00:00
Nicholas Marriott
89543e999d A similar for fix for window_choose: don't rely on the callback always being
called to free data, have a separate free callback and call it from the mode
cleanup code.
2009-07-17 12:12:54 +00:00
Nicholas Marriott
fc17ce0150 Oops, it is always a good idea to get arguments the right way round. 2009-07-17 09:28:27 +00:00
Nicholas Marriott
441c118b63 Memory could be leaked if a second prompt or message appeared while another was
still present, so add a separate prompt free callback and make the _clear
function responsible for calling it if necessary (rather than the individual
2009-07-17 09:26:21 +00:00
Nicholas Marriott
ac55534055 Remove some duplicate code that was causing the status line to be redrawn even
when it hadn't changed.
2009-07-17 07:46:08 +00:00
Nicholas Marriott
821de39b27 Fix arguments to switch-client. 2009-07-17 07:45:42 +00:00
Nicholas Marriott
ede2dd2d3a Typo in grid_duplicate_lines (sy for dy) causing it to write into the wrong
place when copying UTF-8 data. Found by Dan Colish.
2009-07-17 07:45:08 +00:00
Nicholas Marriott
08d32a1522 Update TODO. 2009-07-16 07:35:41 +00:00
Nicholas Marriott
d956ed0760 Typo in grid_duplicate_lines (sy for dy) causing it to write into the wrong
place when copying UTF-8 data. Found by Dan Colish.
2009-07-16 07:35:35 +00:00
Nicholas Marriott
6fe25a08d7 Improved NetBSD current-process detection from Roy Marples. 2009-07-15 17:53:15 +00:00
Nicholas Marriott
222b8e6743 Make status_message_set a variadic printf-like function. No functional change -
helpful for a couple of things coming soon.
2009-07-15 17:50:11 +00:00
Nicholas Marriott
d6908dd9c2 Return -1 not NULL on error, pointed out by Roy Marples. 2009-07-15 17:46:09 +00:00
Nicholas Marriott
ac2ab6501d Add a -k flag to unlink-window which makes it behave the same as the old
kill-window - if a window is linked into only one session it unlinked and
destroyed.
2009-07-15 17:45:29 +00:00
Nicholas Marriott
8bfbc8c61d The man page says that kill-window removes the window entirely, unlinking it
from any sessions. In fact the implementation only affected the current
session, making it the same as unlink-window but destroying the window if it
was linked into only one session (unlinkw gives an error). Change the behaviour
to match what it documented and was originally intended.
2009-07-15 17:45:09 +00:00
Nicholas Marriott
ff90170738 Having to update NSETOPTION/NSETWINDOWOPTION when adding new options is a bit
annoying and it is only use for iterating, so use a sentinel to mark the end of
each array instead. Different fix for a problem pointed out by Kalle Olavi
Niemitalo.
2009-07-15 17:44:47 +00:00
Nicholas Marriott
6ebb1df8fe Add main-pane-height to the options list (was missed before). 2009-07-15 17:44:25 +00:00
Nicholas Marriott
ff500b46c9 For some reason when clearing status/message it was redrawing the entire client
not just the status line. Changing this also revealed the check for the status
line was incorrect when drawing the pane.
2009-07-15 17:44:06 +00:00
Nicholas Marriott
72d56bd614 Instead of faking up a status line in status_redraw, use the same code to
redraw it as to draw the entire screen, just skip all lines but the last.
2009-07-15 17:43:45 +00:00
Nicholas Marriott
ad1945c278 Don't accept input to a window if it not visible. 2009-07-15 17:43:21 +00:00
Nicholas Marriott
82b45b460e The scroll region cannot be one line only, ignore attempts to make it so. 2009-07-15 17:43:02 +00:00
Nicholas Marriott
1e574bb70c Get rid of the PANE_HIDDEN flag in favour of a function, and moving the
decision for whether or not a pane should be drawn out of the layout code and
into the redraw code.

This is needed for the new layout design, getting it in now to make that easier
to work on.
2009-07-15 17:42:44 +00:00
Nicholas Marriott
537c32b6b6 Escape ~, pointed out by tcunha. 2009-07-14 17:44:24 +00:00
Nicholas Marriott
f44ae0535e Need time.h not sys/time.h for time(2). 2009-07-14 07:01:03 +00:00
Nicholas Marriott
910d6282c4 Whoops, chose the wrong one in a conflict. Revert. 2009-07-14 06:54:38 +00:00
Nicholas Marriott
20e322bf9b arg.c is no longer required. 2009-07-14 06:47:46 +00:00
Nicholas Marriott
edd3142d1f Don't need ncurses, use curses. 2009-07-14 06:47:12 +00:00
Nicholas Marriott
097b96ea44 Having fixed flags for single-character getopt options is a bit hard to
maintain and is only going to get worse as more are used. So instead, add a new
uint64_t member to cmd_entry which is a bitmask of upper and lowercase options
accepted by the command.

This means new single character options can be used without the need to add it
explicitly to the list.
2009-07-14 06:43:33 +00:00
Nicholas Marriott
5ccd0025a0 copy-mode and scroll-mode have a -u flag missing from usage, add it. 2009-07-14 06:42:22 +00:00
Nicholas Marriott
d358a352c0 Tidy up and improve target (-t) argument parsing:
- move the code back into cmd.c and merge with the existing functions where
  possible;
- accept "-tttyp0" as well as "-t/dev/ttyp0" for clients;
- when looking up session names, try an exact match first, and if that fails
  look for it as an fnmatch pattern and then as the start of a name - if more
  that one session matches an error is given; so if there is one session called
  "mysession", -tmysession, -tmysess, -tmysess* are equivalent but if there
  is also "mysession2", the last two are errors;
- similarly for windows, if the argument is not a valid index or exact window
  name match, try it against the window names as an fnmatch pattern and a
  prefix.
2009-07-14 06:42:06 +00:00
Nicholas Marriott
e63567d51c Support "alternate screen" mode (terminfo smcup/rmcup) typically used by full
screen interactive programs to preserve the screen contents. When activated, it
saves a copy of the visible grid and disables scrolling into and resizing out
of the history; when deactivated the visible data is restored and the history
reenabled.
2009-07-14 06:40:33 +00:00
Nicholas Marriott
f41ef2198b Missed this declaration in key bindings change. Whoops. 2009-07-14 06:40:03 +00:00
Nicholas Marriott
61bd3ae1c6 Document the -k flag to new-window. 2009-07-14 06:39:44 +00:00
Nicholas Marriott
5ef5bd7c31 Add a "back to indentation" key in copy mode to move the cursor to the first
non-whitespace character. ^ with vi and M-m with emacs key bindings. Another
from Kalle Olavi Niemitalo, thanks.
2009-07-14 06:39:25 +00:00
Nicholas Marriott
7f98193beb Merge three copies of identical code to move the cursor x position into a
single function, from Kalle Olavi Niemitalo.
2009-07-14 06:38:32 +00:00
Nicholas Marriott
d2c3dbc665 If it exist, load a system-wide configuration file /etc/tmux.conf before any
user-specified one.
2009-07-14 06:38:14 +00:00
Tiago Cunha
2f75b07d08 Update. 2009-07-13 18:29:28 +00:00
Tiago Cunha
280619a4e8 Expand leading tilde on commands which expect a filename. 2009-07-13 18:03:18 +00:00
Nicholas Marriott
6db6df882c Update. 2009-07-13 11:33:06 +00:00
Nicholas Marriott
db411ca515 Update TODO. 2009-07-13 06:29:19 +00:00
Nicholas Marriott
3fb3613d34 Limit the history to hlimit not hlimit - 1. This makes a history-limit setting
of 0 work as expected.
2009-07-12 17:12:41 +00:00
Nicholas Marriott
30f47dfc5e Add -r to the synopsis of the paste-buffer command, prompted by jmc. 2009-07-12 17:12:06 +00:00
Nicholas Marriott
27fc963631 When pasting, translate \n into \r. This matches xterm and putty's behaviour,
and makes emacs happy when pasting into some modes. A new -r (raw) flag to
paste-buffer pastes without the translation.

From Kalle Olavi Niemitalo, thanks!
2009-07-12 17:11:39 +00:00
Nicholas Marriott
d8de72ca77 Copy was using the real line length which after resize can be larger than the
screen width. When built with -DDEBUG, this made the grid bounds checking code
kill the server. Restrict copying to the actual width.

From Kalle Olavi Niemitalo, thanks.
2009-07-12 17:11:07 +00:00
Nicholas Marriott
ef5f356da2 paste-buffer -d was not documented. From Kalle Olavi Niemitalo. 2009-07-12 17:10:35 +00:00
Nicholas Marriott
1919deab1f Redraw the status line after renaming a session (it may contain the name). 2009-07-12 17:09:15 +00:00
Nicholas Marriott
fd0971542f Don't send initialisation strings is1/2/3 (barely anything else does) and move
smcup to the first and rmcup to the last sequences output to the terminal. This
allows tmux to use the alternate screen (smcup/rmcup) when available.
2009-07-12 17:08:37 +00:00
Nicholas Marriott
d7b4aa0ff3 Add a default-terminal option to set the starting value of $TERM in new
windows.
2009-07-12 17:07:58 +00:00
Nicholas Marriott
79bc6041c9 Document display-time option which seems to have been missed. 2009-07-12 17:04:21 +00:00
Nicholas Marriott
8be8016a76 When the terminal size is reduced horizontally, don't truncate lines to the new
width, so that if the same lines are later increased in size the content
reappears.
2009-07-12 17:03:11 +00:00
Nicholas Marriott
d4a143a425 Stop in the right place so all the lines selected are copied. Reported by Kalle
Olavi Niemitalo, thanks.
2009-07-12 16:56:56 +00:00
Nicholas Marriott
bf0f56d04e Update TODO. 2009-07-11 19:25:53 +00:00
Nicholas Marriott
0e7c6bdcc7 Update TODO. 2009-07-11 13:48:05 +00:00
Nicholas Marriott
7e8ff69a14 Fix $Id$. 2009-07-09 18:16:36 +00:00
Nicholas Marriott
eee3dd297e New command, if-shell (alias if). Executes the tmux command in the second
argument if the shell command in the first succeeds, for example:

       if "[ -e ~/.tmux.conf.alt ]" "source .tmux.conf.alt"

Written by Tiago Cunha, many thanks.
2009-07-09 18:14:18 +00:00
Nicholas Marriott
5afe17d147 Fix $Id$. 2009-07-09 18:08:29 +00:00
Nicholas Marriott
664a0bd559 Cursor up and down should be limited by the scroll region (cuu should stop at
the scroll region top if starting from below it and cud stop at the bottom if
starting from above). Fixes another vttest test.
2009-07-09 18:08:13 +00:00
Nicholas Marriott
4422b958c3 Don't leak FILE * on malloc failure. From ivoire at users dot sourceforge dot
net.
2009-07-09 18:05:17 +00:00
Nicholas Marriott
295879cced Change inserting and deleting lines inside the scroll region to properly clear
lines that should be inserted/deleted but not moved. Fixes problems with mutt
reported by Brian Lewis, thanks.
2009-07-09 18:04:53 +00:00
Nicholas Marriott
e073441c36 Tidy by removing unused argument from grid_view_{insert,delete}_line_region
functions (currently don't fully work, this is to make fix easier).
2009-07-09 18:04:17 +00:00
Nicholas Marriott
27e9f77a49 Fix two memory leaks when assigning shell variables in configuration
file/command prompt. From Tiago Cunha.
2009-07-09 18:03:28 +00:00
Nicholas Marriott
f8ea82d7dc Update TODO list. 2009-07-09 17:58:54 +00:00
Nicholas Marriott
890db6eaaf Accidently deleted default-command. 2009-07-08 18:12:57 +00:00
Nicholas Marriott
99395856ff Bring spacing into line. 2009-07-08 18:07:09 +00:00
Nicholas Marriott
9cf68ac868 Whoops, that shouldn't have been there. 2009-07-08 18:05:33 +00:00
Nicholas Marriott
2ddcb51df3 Fix $Id$. 2009-07-08 18:03:03 +00:00
Nicholas Marriott
9875be3327 When reinitialising the screen, do not omit to clear the last line. 2009-07-08 18:02:31 +00:00
Nicholas Marriott
a182502af0 Don't let ambiguous commands override an exact alias match: eg if commands
"abc-1", "abc-2", "abc-3" exist and "abc-3" has the alias "abc", "tmux abc"
should execute abc-3, not complain about the command being ambiguous.
2009-07-08 18:01:55 +00:00
Nicholas Marriott
86504af149 Rename the global options variables to be shorter and to make session options
clear. No functional change, getting this out of the way to make later options
changes easier.
2009-07-08 18:01:31 +00:00
Nicholas Marriott
1825609d8d Handle empty or unset TERM correctly; also fix a fatal() message while here. 2009-07-08 17:58:32 +00:00
Nicholas Marriott
43ff216fa6 When sending a "protocol mismatch" error message, tell the client to exit
afterwards, otherwise it hangs.
2009-07-08 17:58:09 +00:00
Nicholas Marriott
ff54332b66 The fix for default-path (use target session options instead of global options)
is required here as well, doh.
2009-07-08 17:57:51 +00:00
Nicholas Marriott
84da2f32ec Minor fix: look for default-path in the options for the specified session first
rather than just the global options. From Brandon Mercer, thanks.
2009-07-08 17:57:27 +00:00
Nicholas Marriott
b7a272fe6d Add a section summarising how options work, make the distinction between window
and session options clearer, and fix the incorrect synopses and descriptions of
show-options and show-window-options.
2009-07-08 17:57:07 +00:00
Nicholas Marriott
9e5a581307 When unlocking the server, don't try to clear the prompt on clients without a
prompt (such as the one issuing the unlock request).

This caused the server to die if the wrong password was entered when unlocking
from the command line with -U (nasty).
2009-07-08 17:54:36 +00:00
Nicholas Marriott
f34f1fd78d Sync. 2009-07-07 23:08:42 +00:00
Nicholas Marriott
a476d4c587 This is not really important or major. 2009-07-06 18:53:24 +00:00
Nicholas Marriott
21f8ed50db Next will be 1.0. 2009-07-06 18:21:17 +00:00
153 changed files with 11915 additions and 6874 deletions

38
CHANGES
View File

@@ -1,3 +1,39 @@
CHANGES FROM 0.9 TO 1.0, 20 Sept 2009
* Option to alter the format of the window title set by tmux.
* Backoff for a while after multiple incorrect password attempts.
* Quick display of pane numbers (C-b q).
* Better choose-window, choose-session commands and a new choose-client command.
* Option to request multiple responses when using command-prompt.
* Improved environment handling.
* Combine wrapped lines when pasting.
* Option to override terminal settings (terminal-overrides).
* Use the full range of ACS characters for drawing pane separator lines.
* Customisable mode keys.
* Status line colour options, with embedded colours in status-left/right, and
an option to centre the window list.
* Much improved layouts, including both horizontal and vertical splitting.
* Optional visual bell, activity and content indications.
* Set the utf8 and status-utf8 options when the server is started with -u.
* display-message command to show a message in the status line, by default some
information about the current window.
* Improved current process detection on NetBSD.
* unlink-window -k is now the same as kill-window.
* attach-session now works from inside tmux.
* A system-wide configuration file, /etc/tmux.conf.
* A number of new commands in copy mode, including searching.
* Panes are now specified using the target (-t) notation.
* -t now accepts fnmatch(3) patterns and looks for prefixes.
* Translate \r into \n when pasting.
* Support for binding commands to keys without the prefix key
* Support for alternate screen (terminfo smcup/rmcup).
* Maintain data that goes off screen after reducing the window size, so it can
be restored when the size is increased again.
* New if-shell command to test a shell command before running a tmux command.
* tmux now works as the shell.
* Man page reorganisation.
* Many minor additions, much code tidying and several bug fixes.
CHANGES FROM 0.8 TO 0.9, 01 July 2009 CHANGES FROM 0.8 TO 0.9, 01 July 2009
* Major changes to build infrastructure: cleanup of makefiles and addition * Major changes to build infrastructure: cleanup of makefiles and addition
@@ -1322,7 +1358,7 @@ The list of older changes is below.
(including mutt, emacs). No status bar yet and no key remapping or other (including mutt, emacs). No status bar yet and no key remapping or other
customisation. customisation.
$Id: CHANGES,v 1.299 2009-07-01 22:15:16 nicm Exp $ $Id: CHANGES,v 1.300 2009-09-20 18:54:21 nicm Exp $
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms

61
FAQ
View File

@@ -42,16 +42,17 @@ include as much of the following information as possible:
Please send feature requests by email to nicm@users.sourceforge.net. Please send feature requests by email to nicm@users.sourceforge.net.
* Why do you use the screen termcap inside tmux? It sucks. * Why do you use the screen terminal description inside tmux? It sucks.
It is already widely available. It is planned to change to something else It is already widely available. It is planned to change to something else such
such as xterm-color at some point, if possible. as xterm-xfree86 at some point, if possible.
* I don't see any colour in my terminal! Help! * I don't see any colour in my terminal! Help!
On some platforms, common termcaps such as xterm do not include colour. screen On some platforms, common terminal descriptions such as xterm do not include
ignores this, tmux does not. If the terminal emulator in use supports colour, colour. screen ignores this, tmux does not. If the terminal emulator in use
use a termcap which correctly lists this, such as xterm-color. supports colour, use a value for TERM which correctly lists this, such as
xterm-color.
* tmux freezes my terminal when I attach to a session. I even have to kill -9 * tmux freezes my terminal when I attach to a session. I even have to kill -9
the shell it was started from to recover! the shell it was started from to recover!
@@ -92,13 +93,22 @@ checking the LC_ALL, LC_CTYPE and LANG environment variables. list-clients may
be used to check if this is detected correctly; if not, the -u command-line be used to check if this is detected correctly; if not, the -u command-line
flag may be specified when creating or attaching a client to a tmux session: flag may be specified when creating or attaching a client to a tmux session:
$ tmux -u new $ tmux -u new
* How do I use a 256 colour terminal? * How do I use a 256 colour terminal?
tmux will attempt to detect a 256 colour terminal both by looking at the Co Provided the underlying terminal supports 256 colours, it is usually sufficient
termcap entry and, as this is broken for some terminals such as xterm-256color, to add the following to ~/.tmux.conf:
by looking for the string "256col" in the termcap name.
set -g default-terminal "screen-256color"
Note that some platforms do not support "screen-256color" ("infocmp
screen-256color" will return an error) - in this case see the next entry in
this FAQ.
tmux attempts to detect a 256 colour terminal both by looking at the colors
terminfo entry and by looking for the string "256col" in the TERM environment
variable.
If both these methods fail, the -2 flag may be passed to tmux when attaching If both these methods fail, the -2 flag may be passed to tmux when attaching
to a session to indicate the terminal supports 256 colours. to a session to indicate the terminal supports 256 colours.
@@ -106,22 +116,18 @@ to a session to indicate the terminal supports 256 colours.
* vim or $otherprogram doesn't display 256 colours. What's up? * vim or $otherprogram doesn't display 256 colours. What's up?
Some programs attempt to detect the number of colours a terminal is capable of Some programs attempt to detect the number of colours a terminal is capable of
by checking the Co termcap entry. However, this is not reliable, and in any by checking the colors terminfo or Co termcap entry. However, this is not
case is missing from the "screen" termcap used inside tmux. reliable, and in any case is missing from the "screen" terminal description
used inside tmux.
There are three options to allow programs to recognise they are running on There are two options (aside from using "screen-256color") to allow programs to
a 256-colour terminal inside tmux: recognise they are running on a 256-colour terminal inside tmux:
- Manually force the application to use 256 colours always or if TERM is set to - Manually force the application to use 256 colours always or if TERM is set to
screen. For vim, you can do this by overriding the t_Co option, see screen. For vim, you can do this by overriding the t_Co option, see
http://vim.wikia.com/wiki/256_colors_in_vim. http://vim.wikia.com/wiki/256_colors_in_vim.
- If the platform includes it, using the "screen-256color" termcap (set - Creating a custom terminfo file that includes colors#256 in ~/.terminfo and
TERM=screen-256color). "infocmp screen-256color" can be used to check if this using it instead. These may be compiled with tic(1).
is supported. It is not currently possible to set this globally inside tmux
but it may be done in a shell startup script by checking if TERM is screen
and exporting TERM=screen-256color instead.
- Creating a custom terminfo file that includes Co#256 in ~/.terminfo and using
it instead. These may be compiled with tic(1).
* How do I make Ctrl-PgUp and Ctrl-PgDn work in vim? * How do I make Ctrl-PgUp and Ctrl-PgDn work in vim?
@@ -187,11 +193,12 @@ Automatic window renaming may use a lot of CPU, particularly on slow computers:
if this is a problem, turn it off with "setw -g automatic-rename off". If this if this is a problem, turn it off with "setw -g automatic-rename off". If this
doesn't fix it, please report the problem. doesn't fix it, please report the problem.
* How do I prevent tmux from resizing my PuTTY window? * I use PuTTY and my tmux window pane separators are all qqqqqqqqq's!
This isn't tmux's fault, but happens because the initialisation strings for the PuTTY is using a character set translation that doesn't support ACS line
terminal in use (set through TERM) request it. PuTTY can be told to ignore such drawing. With a Unicode font, try setting PuTTY to use a different translation
requests: in the configuration window under Terminal -> Features, check the on the Window -> Translation configuration page. For example, change UTF-8 to
"Disable remote-controlled terminal resizing" box. ISO-8859-1 or CP437. It may also be necessary to adjust the way PuTTY treats
line drawing characters in the lower part of the same configuration page.
$Id: FAQ,v 1.23 2009-07-01 19:49:56 nicm Exp $ $Id: FAQ,v 1.29 2009-08-08 20:46:26 nicm Exp $

View File

@@ -1,23 +1,15 @@
# $Id: GNUmakefile,v 1.107 2009-07-01 22:10:06 nicm Exp $ # $Id: GNUmakefile,v 1.114 2009-09-20 18:54:21 nicm Exp $
.PHONY: clean .PHONY: clean
VERSION= 0.9 VERSION= 1.0
#FDEBUG= 1 #FDEBUG= 1
CC?= gcc CC?= gcc
CFLAGS+= -DBUILD="\"$(VERSION)\"" CFLAGS+= -DBUILD="\"$(VERSION)\""
LDFLAGS+= -L/usr/local/lib LDFLAGS+= -L/usr/local/lib
LIBS+= -lncurses LIBS+=
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
ifeq ($(shell (LC_ALL=C $(CC) -v 2>&1|awk '/gcc version 4/') || true), )
CPPFLAGS:= -I. -I- $(CPPFLAGS)
else
CPPFLAGS:= -iquote. $(CPPFLAGS)
endif
ifdef FDEBUG ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG CFLAGS+= -g -ggdb -DDEBUG
@@ -27,6 +19,17 @@ CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
endif endif
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
ifeq ($(shell (LC_ALL=C $(CC) -v 2>&1|awk '/gcc version 4|clang/') || true), )
CPPFLAGS:= -I. -I- $(CPPFLAGS)
else
CPPFLAGS:= -iquote. $(CPPFLAGS)
ifdef FDEBUG
CFLAGS+= -Wno-pointer-sign
endif
endif
PREFIX?= /usr/local PREFIX?= /usr/local
INSTALLDIR= install -d INSTALLDIR= install -d
INSTALLBIN= install -g bin -o root -m 555 INSTALLBIN= install -g bin -o root -m 555
@@ -45,9 +48,12 @@ depend: $(SRCS)
$(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend $(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend
clean: clean:
rm -f tmux *.o .depend *~ *.core *.log compat/*.o rm -f tmux *.o *~ *.core *.log compat/*.o
clean-all: clean clean-depend:
rm -f .depend
clean-all: clean clean-depend
rm -f config.h config.mk rm -f config.h config.mk
install: all install: all
@@ -55,3 +61,5 @@ install: all
$(INSTALLBIN) tmux $(DESTDIR)$(PREFIX)/bin/tmux $(INSTALLBIN) tmux $(DESTDIR)$(PREFIX)/bin/tmux
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/man/man1 $(INSTALLDIR) $(DESTDIR)$(PREFIX)/man/man1
$(INSTALLMAN) tmux.1 $(DESTDIR)$(PREFIX)/man/man1/tmux.1 $(INSTALLMAN) tmux.1 $(DESTDIR)$(PREFIX)/man/man1/tmux.1
-include .depend

View File

@@ -1,25 +1,16 @@
# $Id: Makefile,v 1.142 2009-07-01 22:10:06 nicm Exp $ # $Id: Makefile,v 1.149 2009-09-20 18:54:21 nicm Exp $
.SUFFIXES: .c .o .SUFFIXES: .c .o
.PHONY: clean .PHONY: clean
VERSION= 0.9 VERSION= 1.0
#FDEBUG= 1 #FDEBUG= 1
CC?= cc CC?= cc
CFLAGS+= -DBUILD="\"$(VERSION)\"" CFLAGS+= -DBUILD="\"$(VERSION)\""
LDFLAGS+= -L/usr/local/lib LDFLAGS+= -L/usr/local/lib
LIBS+= -lncurses LIBS+=
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
CCV!= (LC_ALL=C ${CC} -v 2>&1|awk '/gcc version 4/') || true
.if empty(CCV)
CPPFLAGS:= -I. -I- -I/usr/local/include ${CPPFLAGS}
.else
CPPFLAGS:= -iquote. -I/usr/local/include ${CPPFLAGS}
.endif
.ifdef FDEBUG .ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG CFLAGS+= -g -ggdb -DDEBUG
@@ -29,6 +20,18 @@ CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
.endif .endif
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
CCV!= (LC_ALL=C ${CC} -v 2>&1|awk '/gcc version 4|clang/') || true
.if empty(CCV)
CPPFLAGS:= -I. -I- -I/usr/local/include ${CPPFLAGS}
.else
CPPFLAGS:= -iquote. -I/usr/local/include ${CPPFLAGS}
.ifdef FDEBUG
CFLAGS+= -Wno-pointer-sign
.endif
.endif
PREFIX?= /usr/local PREFIX?= /usr/local
INSTALLDIR= install -d INSTALLDIR= install -d
INSTALLBIN= install -g bin -o root -m 555 INSTALLBIN= install -g bin -o root -m 555
@@ -50,9 +53,12 @@ depend:
mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c} mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c}
clean: clean:
rm -f tmux *.o .depend *~ *.core *.log compat/*.o rm -f tmux *.o *~ *.core *.log compat/*.o
clean-all: clean clean-depend:
rm -f .depend
clean-all: clean clean-depend
rm -f config.h config.mk rm -f config.h config.mk
install: all install: all

6
NOTES
View File

@@ -41,10 +41,6 @@ The following is a summary of major features implemented in this version:
- A configuration file. - A configuration file.
- UTF-8 support. - UTF-8 support.
And major missing features:
- No support for programs changing termios(4) settings or other tty(4) ioctls.
A more extensive, but rough, todo list is included in the TODO file. A more extensive, but rough, todo list is included in the TODO file.
tmux also depends on several features of the client terminal (TERM), if these tmux also depends on several features of the client terminal (TERM), if these
@@ -87,4 +83,4 @@ welcome. Please send by email to:
-- Nicholas Marriott <nicm@users.sf.net> -- Nicholas Marriott <nicm@users.sf.net>
$Id: NOTES,v 1.48 2009-07-01 19:49:56 nicm Exp $ $Id: NOTES,v 1.49 2009-07-06 18:53:24 nicm Exp $

98
TODO
View File

@@ -1,5 +1,4 @@
- window creation/idle time - window creation/idle time
- could use bsearch all over the place or get rid of smaller tables (clientmsg)
- better errors when creating new windows/sessions (how?) - better errors when creating new windows/sessions (how?)
- implicitly add exec to the commands for new windows (switch to disable it)? - implicitly add exec to the commands for new windows (switch to disable it)?
- it would be nice to have multichar commands eg C-b K K - it would be nice to have multichar commands eg C-b K K
@@ -7,21 +6,16 @@
extend list-clients to list clients attached to a session (-a for all?) extend list-clients to list clients attached to a session (-a for all?)
bring back detach-session to detach all clients on a session? bring back detach-session to detach all clients on a session?
- allow fnmatch for -c, so that you can, eg, detach all clients - allow fnmatch for -c, so that you can, eg, detach all clients
- bind non prefix keys
- garbage collect window history (100 lines at a time?) if it hasn't been used - garbage collect window history (100 lines at a time?) if it hasn't been used
in $x time (need window creation/use times) in $x time (need window creation/use times)
- lift SHRT_MAX limits for history? - lift SHRT_MAX limits for history?
- audit copy/scroll and other modes for problems with very small windows - better mode features: search
- better mode features: search, back word, forward word, etc
- flags to centre screen in window - flags to centre screen in window
- better terminal emulation (identify, insert mode, some other bits) - better terminal emulation
- audit for leftover/unused code
- activity/bell should be per-window not per-link? what if it is cur win in - activity/bell should be per-window not per-link? what if it is cur win in
session not being watched? session not being watched?
- tidy up window modes
- next prev word etc in command prompt; also ^K - next prev word etc in command prompt; also ^K
- many more info() displays for various things - many more info() displays for various things
- vi half page scroll
- backspace should perhaps wrap backwards over newlines which were not moved - backspace should perhaps wrap backwards over newlines which were not moved
down by a newline: screen and the OS X terminal does this but xterm and most down by a newline: screen and the OS X terminal does this but xterm and most
others do not. this might be hard: a flag for each grid line (top bit of size others do not. this might be hard: a flag for each grid line (top bit of size
@@ -31,17 +25,10 @@
- use a better termcap internally instead of screen, perhaps xterm - use a better termcap internally instead of screen, perhaps xterm
- kill all but current pane - kill all but current pane
- fix rxvt cursor fg issue (text under cursor can have non-white fg) - fix rxvt cursor fg issue (text under cursor can have non-white fg)
- key handling sucks a bit and may need to be reworked
- some people find first window being 0 rather than 1 is awkward on the
keyboard
- client sx/sy should be in tty, then can let the terminal wrap at edge - client sx/sy should be in tty, then can let the terminal wrap at edge
to allow xterm to pick up it should be one line for its c/p to allow xterm to pick up it should be one line for its c/p
- should be able to move to a hidden pane and it would be moved into view. pane - 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 number in status line/top-right would be cool for this
- command to run something without a window at all - output to
window-more. what for? isnt this the same as doing it w/ splitw/neww now?
- would be nice if tmux could be the shell (tmux attach, but hard link to tmux
binary as "tmuxsh" or wrapper script?) problems with tty dev permissions
- support other mouse modes (highlight etc) and use it in copy mode - 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? - set-remain-on-exit is a bit of a hack, some way to do it generically?
- set-option should be set-session-option and should be overall global options - set-option should be set-session-option and should be overall global options
@@ -49,44 +36,71 @@
also quiet, utf8 and maybe other flags? also quiet, utf8 and maybe other flags?
-g is a bit unexpected in conf file -g is a bit unexpected in conf file
- clear window title on exit - clear window title on exit
- refer to windows by name etc (duplicates? fnmatch?)
- the output code (tty.c) could do with optimisation depending on term - the output code (tty.c) could do with optimisation depending on term
capibilities capibilities
- would be nice to be able to use "--" to mark start of command w/ neww etc - would be nice to be able to use "--" to mark start of command w/ neww etc
to avoid quoting to avoid quoting
- goto line and search history in copy/scroll modes - goto line and search history in copy/scroll modes
- a command to display the status line briefly when it is turned off
- clone session command - clone session command
- make command sequences more usable: don't require space after ;, handle - make command sequences more usable: don't require space after ;, handle
errors better errors better
- might be nice if attach-session behaved like switch-client inside an
existing client
- key to switch to copy mode from scroll mode - key to switch to copy mode from scroll mode
- attach should have a flag to create session if it doesn't exist - attach should have a flag to create session if it doesn't exist
- layout/split stuff: - rename split-window -> split-pane??
** NEW layout design:
1. finish rewrite manual with tree of layout_cell
2. convert automatic layout modes to produce a tree and make
them one-off operations
3. move any size/position details from window_pane to layout_cell
3.5. fix -p/-l on split
4. a way to address panes by name ("top-left") and position ("0,0")
TO TEST: force-width/height OK, respawn-window, rotate-window OK, break-pane??
** rename split-window -> split-pane
- fix UTF-8 guesswork on sparc64, improve tty checks - fix UTF-8 guesswork on sparc64, improve tty checks
- choice and more mode would be better per client than per window? - choice and more mode would be better per client than per window?
- hooks to which commands may be attached, for example: tmux add-hook
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
$HOME/.tmux-session.conf
- get it passing all the vttest tests that don't require resizing the terminal
- esc seq to set window title should be documented and should set
automatic-rename
- way to set socket path from config file
- XXX once env stuff is in, default-path and VISUAL/EDITOR should be picked up
when session is started
- what about utmp etc? can tmux update it like screen? setgid?
- H/M/L commands in copy mode with vi-keys, for jumping to the top/middle/last
line on the screen
- split list-windows into separate list-windows and list-panes
- warts on current naming:
- display-time but message-fg/bg/attr
- list-* vs show-*
- server-info
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
- pcvt25 doesn't work properly, why? (bce?)
- tidy up and prioritise todo list ;-)
- it is only possible to specify 8 colours to fg/bg options; should be able to
set 256 as well
- neww and attach can create a session if none exists?
would work fine with config file since
- a way for force-width/height to apply to only one pane (how?)
- **** a command to run something without a window and send any output to the
window-more. if no output, info() a line saying "'%s' returned %d". so i can
bind mpc control commands to function keys ;-)
- command to list what is actually running in each window with command line,
pid (need some adaption of the osdep code)
- string option to change/remove the symbols (*-+ etc) in status line
- support for bce
- it would be nice if the start/end line keys in copy mode were aware of
wrapped lines
- per session locking
- some way to force a screen to use the entire terminal even if it is forced - 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) to be smaller by other clients. pan smaller terminal? (like screen F)
- close/redirect stderr when popen to child proc for #() in status line -- idea of a "view" onto a window, need base x/y offsets
- if-shell-command command to run a tmux command if a shell command returns true for redraw
- hooks to which commands may be attached, for example: - a window option which means data is echoed to all panes in a window
tmux add-hook "new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file $HOME/.tmux-session.conf - support running tmux from inside tmux [#(), if-shell] --
- get it passing all the vttest tests that don't require resizing the terminal generic system-like function which may take a callback
- does tmux require a exmple conf? where does it go? also sets up environment (TMUX) and has a timeout
- there are an awful lot of commands. maybe separate man page for conf for #(): command schedular, status line queues it with a time, run in
file/commands -similar to ssh/ssh_config? main loop, and uses most recent result -- can also be used for persistent
- esc seq to set window title should be documented and should set automatic-rename commands which never exit just continually output
- *** get rid of PANE_HIDDEN -- initially just check for outside window for if-shell, callback??
- way to set socket path from config file - handle resize better in copy mode
- the "window with one pane" vs window distinction is weird, eg you can't kill-pane the last pane - way to copy stuff that is off screen due to resize
- fix line wrapping c&p problems in xterm etc
- a way to address panes by name ("top-left") and position ("0,0")
- ability to specify multiple prefix keys
- commands should be able to succeed or fail and have || or && for command
lists
- support the mouse wheel to scroll through history

194
arg.c
View File

@@ -1,194 +0,0 @@
/* $Id: arg.c,v 1.6 2009-06-25 15:25:45 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <fnmatch.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
struct client *arg_lookup_client(const char *);
struct session *arg_lookup_session(const char *);
struct client *
arg_lookup_client(const char *name)
{
struct client *c;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && strcmp(name, c->tty.path) == 0)
return (c);
}
return (NULL);
}
struct session *
arg_lookup_session(const char *name)
{
struct session *s, *newest = NULL;
struct timeval *tv;
u_int i;
tv = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL || fnmatch(name, s->name, 0) != 0)
continue;
if (tv == NULL || timercmp(&s->tv, tv, >)) {
newest = s;
tv = &s->tv;
}
}
return (newest);
}
struct client *
arg_parse_client(const char *arg)
{
struct client *c;
char *arg2;
size_t n;
if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
arg2 = xstrdup(arg);
/* Trim a trailing : if any from the argument. */
n = strlen(arg2);
if (n && arg2[n - 1] == ':')
arg2[n - 1] = '\0';
/* Try and look up the client name. */
c = arg_lookup_client(arg2);
xfree(arg2);
return (c);
}
return (NULL);
}
struct session *
arg_parse_session(const char *arg)
{
struct session *s;
struct client *c;
char *arg2;
size_t n;
if (arg != NULL && (arg[0] != ':' || arg[1] != '\0')) {
arg2 = xstrdup(arg);
/* Trim a trailing : if any from the argument. */
n = strlen(arg2);
if (n && arg2[n - 1] == ':')
arg2[n - 1] = '\0';
/* See if the argument matches a session. */
if ((s = arg_lookup_session(arg2)) != NULL) {
xfree(arg2);
return (s);
}
/* If not try a client. */
if ((c = arg_lookup_client(arg2)) != NULL) {
xfree(arg2);
return (c->session);
}
xfree(arg2);
}
return (NULL);
}
int
arg_parse_window(const char *arg, struct session **s, int *idx)
{
char *arg2, *ptr;
const char *errstr;
*idx = -1;
/* Handle no argument or a single :. */
if (arg == NULL || (arg[0] == ':' && arg[1] == '\0')) {
*s = arg_parse_session(NULL);
return (0);
}
/* Find the separator if any. */
arg2 = xstrdup(arg);
ptr = strrchr(arg2, ':');
/*
* If it is first, this means no session name, so use current session
* and try to convert the rest as index.
*/
if (ptr == arg2) {
*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xfree(arg2);
return (1);
}
xfree(arg2);
*s = arg_parse_session(NULL);
return (0);
}
/* If missing, try as an index, else look up immediately. */
if (ptr == NULL) {
*idx = strtonum(arg2, 0, INT_MAX, &errstr);
if (errstr == NULL) {
/* This is good as an index; use current session. */
xfree(arg2);
*s = arg_parse_session(NULL);
return (0);
}
*idx = -1;
goto lookup;
}
/* If last, strip it and look up as a session. */
if (ptr[1] == '\0') {
*ptr = '\0';
goto lookup;
}
/* Present but not first and not last. Break and convert both. */
*ptr = '\0';
*idx = strtonum(ptr + 1, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xfree(arg2);
return (1);
}
lookup:
/* Look up as session. */
*s = arg_parse_session(arg2);
xfree(arg2);
if (*s == NULL)
return (1);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: buffer-poll.c,v 1.14 2009-06-25 16:22:36 nicm Exp $ */ /* $Id: buffer-poll.c,v 1.16 2009-08-19 09:28:10 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,10 +29,8 @@ buffer_poll(struct pollfd *pfd, struct buffer *in, struct buffer *out)
{ {
ssize_t n; ssize_t n;
#ifdef HAVE_POLL
if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP)) if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
return (-1); return (-1);
#endif
if (pfd->revents & POLLIN) { if (pfd->revents & POLLIN) {
buffer_ensure(in, BUFSIZ); buffer_ensure(in, BUFSIZ);
n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in)); n = read(pfd->fd, BUFFER_IN(in), BUFFER_FREE(in));

View File

@@ -1,4 +1,4 @@
/* $Id: buffer.c,v 1.7 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: buffer.c,v 1.8 2009-08-21 21:09:13 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -100,9 +100,6 @@ buffer_remove(struct buffer *b, size_t size)
void void
buffer_write(struct buffer *b, const void *data, size_t size) buffer_write(struct buffer *b, const void *data, size_t size)
{ {
if (size == 0)
fatalx("zero size");
buffer_ensure(b, size); buffer_ensure(b, size);
memcpy(BUFFER_IN(b), data, size); memcpy(BUFFER_IN(b), data, size);
buffer_add(b, size); buffer_add(b, size);
@@ -127,7 +124,7 @@ buffer_write8(struct buffer *b, uint8_t n)
{ {
buffer_ensure(b, 1); buffer_ensure(b, 1);
BUFFER_IN(b)[0] = n; BUFFER_IN(b)[0] = n;
buffer_add(b, 1); b->size++;
} }
/* Extract an 8-bit value. */ /* Extract an 8-bit value. */

30
cfg.c
View File

@@ -1,4 +1,4 @@
/* $Id: cfg.c,v 1.18 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cfg.c,v 1.22 2009-08-24 16:27:03 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -51,25 +51,15 @@ cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
} }
int int
load_cfg(const char *path, char **cause) load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
{ {
FILE *f; FILE *f;
u_int n; u_int n;
struct stat sb;
char *buf, *line, *ptr; char *buf, *line, *ptr;
size_t len; size_t len;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx ctx; struct cmd_ctx ctx;
if (stat(path, &sb) != 0) {
xasprintf(cause, "%s: %s", path, strerror(errno));
return (-1);
}
if (!S_ISREG(sb.st_mode)) {
xasprintf(cause, "%s: not a regular file", path);
return (-1);
}
if ((f = fopen(path, "rb")) == NULL) { if ((f = fopen(path, "rb")) == NULL) {
xasprintf(cause, "%s: %s", path, strerror(errno)); xasprintf(cause, "%s: %s", path, strerror(errno));
return (1); return (1);
@@ -97,16 +87,20 @@ load_cfg(const char *path, char **cause)
continue; continue;
cfg_cause = NULL; cfg_cause = NULL;
ctx.msgdata = NULL; if (ctxin == NULL) {
ctx.cursession = NULL; ctx.msgdata = NULL;
ctx.curclient = NULL; ctx.curclient = NULL;
ctx.cmdclient = NULL;
} else {
ctx.msgdata = ctxin->msgdata;
ctx.curclient = ctxin->curclient;
ctx.cmdclient = ctxin->cmdclient;
}
ctx.error = cfg_error; ctx.error = cfg_error;
ctx.print = cfg_print; ctx.print = cfg_print;
ctx.info = cfg_print; ctx.info = cfg_print;
ctx.cmdclient = NULL;
cfg_cause = NULL; cfg_cause = NULL;
cmd_list_exec(cmdlist, &ctx); cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
@@ -122,6 +116,8 @@ load_cfg(const char *path, char **cause)
return (0); return (0);
error: error:
if (line != NULL)
xfree(line);
fclose(f); fclose(f);
xasprintf(&ptr, "%s: %s at line %u", path, *cause, n); xasprintf(&ptr, "%s: %s at line %u", path, *cause, n);

View File

@@ -1,4 +1,4 @@
/* $Id: client-fn.c,v 1.6 2009-03-04 17:24:07 nicm Exp $ */ /* $Id: client-fn.c,v 1.10 2009-08-14 21:04:04 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,6 +20,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -63,30 +64,27 @@ client_fill_session(struct msg_command_data *data)
void void
client_write_server( client_write_server(
struct client_ctx *cctx, enum hdrtype type, void *buf, size_t len) struct client_ctx *cctx, enum msgtype type, void *buf, size_t len)
{ {
struct hdr hdr; imsg_compose(&cctx->ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
hdr.type = type;
hdr.size = len;
buffer_write(cctx->srv_out, &hdr, sizeof hdr);
if (buf != NULL && len > 0)
buffer_write(cctx->srv_out, buf, len);
} }
void void
client_write_server2(struct client_ctx *cctx, client_suspend(void)
enum hdrtype type, void *buf1, size_t len1, void *buf2, size_t len2)
{ {
struct hdr hdr; struct sigaction act;
hdr.type = type; memset(&act, 0, sizeof act);
hdr.size = len1 + len2; sigemptyset(&act.sa_mask);
buffer_write(cctx->srv_out, &hdr, sizeof hdr); act.sa_flags = SA_RESTART;
if (buf1 != NULL && len1 > 0) act.sa_handler = SIG_DFL;
buffer_write(cctx->srv_out, buf1, len1); if (sigaction(SIGTSTP, &act, NULL) != 0)
if (buf2 != NULL && len2 > 0) fatal("sigaction failed");
buffer_write(cctx->srv_out, buf2, len2);
act.sa_handler = sighandler;
if (sigaction(SIGCONT, &act, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
} }

View File

@@ -1,159 +0,0 @@
/* $Id: client-msg.c,v 1.19 2009-06-25 15:25:45 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
int client_msg_fn_detach(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_error(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_shutdown(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exit(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_exited(struct hdr *, struct client_ctx *, char **);
int client_msg_fn_suspend(struct hdr *, struct client_ctx *, char **);
struct client_msg {
enum hdrtype type;
int (*fn)(struct hdr *, struct client_ctx *, char **);
};
struct client_msg client_msg_table[] = {
{ MSG_DETACH, client_msg_fn_detach },
{ MSG_ERROR, client_msg_fn_error },
{ MSG_EXIT, client_msg_fn_exit },
{ MSG_EXITED, client_msg_fn_exited },
{ MSG_SHUTDOWN, client_msg_fn_shutdown },
{ MSG_SUSPEND, client_msg_fn_suspend },
};
int
client_msg_dispatch(struct client_ctx *cctx, char **error)
{
struct hdr hdr;
struct client_msg *msg;
u_int i;
if (BUFFER_USED(cctx->srv_in) < sizeof hdr)
return (1);
memcpy(&hdr, BUFFER_OUT(cctx->srv_in), sizeof hdr);
if (BUFFER_USED(cctx->srv_in) < (sizeof hdr) + hdr.size)
return (1);
buffer_remove(cctx->srv_in, sizeof hdr);
for (i = 0; i < nitems(client_msg_table); i++) {
msg = client_msg_table + i;
if (msg->type == hdr.type) {
if (msg->fn(&hdr, cctx, error) != 0)
return (-1);
return (0);
}
}
fatalx("unexpected message");
}
int
client_msg_fn_error(struct hdr *hdr, struct client_ctx *cctx, char **error)
{
if (hdr->size == SIZE_MAX)
fatalx("bad MSG_ERROR size");
*error = xmalloc(hdr->size + 1);
buffer_read(cctx->srv_in, *error, hdr->size);
(*error)[hdr->size] = '\0';
return (-1);
}
int
client_msg_fn_detach(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_DETACH size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_DETACH;
return (0);
}
int
client_msg_fn_shutdown(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_SHUTDOWN size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_SHUTDOWN;
return (0);
}
int
client_msg_fn_exit(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXIT size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->flags |= CCTX_EXIT;
return (0);
}
int
client_msg_fn_exited(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
if (hdr->size != 0)
fatalx("bad MSG_EXITED size");
return (-1);
}
int
client_msg_fn_suspend(
struct hdr *hdr, unused struct client_ctx *cctx, unused char **error)
{
struct sigaction act;
if (hdr->size != 0)
fatalx("bad MSG_SUSPEND size");
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
act.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &act, NULL) != 0)
fatal("sigaction failed");
act.sa_handler = sighandler;
if (sigaction(SIGCONT, &act, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
return (0);
}

217
client.c
View File

@@ -1,4 +1,4 @@
/* $Id: client.c,v 1.53 2009-07-01 23:06:32 nicm Exp $ */ /* $Id: client.c,v 1.70 2009-09-03 21:06:30 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,19 +33,19 @@
#include "tmux.h" #include "tmux.h"
void client_send_environ(struct client_ctx *);
void client_handle_winch(struct client_ctx *); void client_handle_winch(struct client_ctx *);
int int
client_init(char *path, struct client_ctx *cctx, int start_server, int flags) client_init(char *path, struct client_ctx *cctx, int cmdflags, int flags)
{ {
struct sockaddr_un sa; struct sockaddr_un sa;
struct stat sb; struct stat sb;
struct msg_identify_data data; struct msg_identify_data data;
struct winsize ws; struct winsize ws;
size_t size; size_t size;
int mode; int fd, fd2, mode;
struct buffer *b; char *name, *term;
char *name;
#ifdef HAVE_SETPROCTITLE #ifdef HAVE_SETPROCTITLE
char rpathbuf[MAXPATHLEN]; char rpathbuf[MAXPATHLEN];
#endif #endif
@@ -57,8 +57,8 @@ client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
#endif #endif
if (lstat(path, &sb) != 0) { if (lstat(path, &sb) != 0) {
if (start_server && errno == ENOENT) { if (cmdflags & CMD_STARTSERVER && errno == ENOENT) {
if ((cctx->srv_fd = server_start(path)) == -1) if ((fd = server_start(path)) == -1)
goto start_failed; goto start_failed;
goto server_started; goto server_started;
} }
@@ -77,15 +77,14 @@ client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
goto not_found; goto not_found;
} }
if ((cctx->srv_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket"); fatal("socket");
if (connect( if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
cctx->srv_fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
if (errno == ECONNREFUSED) { if (errno == ECONNREFUSED) {
if (unlink(path) != 0 || !start_server) if (unlink(path) != 0 || !(cmdflags & CMD_STARTSERVER))
goto not_found; goto not_found;
if ((cctx->srv_fd = server_start(path)) == -1) if ((fd = server_start(path)) == -1)
goto start_failed; goto start_failed;
goto server_started; goto server_started;
} }
@@ -93,34 +92,40 @@ client_init(char *path, struct client_ctx *cctx, int start_server, int flags)
} }
server_started: server_started:
if ((mode = fcntl(cctx->srv_fd, F_GETFL)) == -1) if ((mode = fcntl(fd, F_GETFL)) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
if (fcntl(cctx->srv_fd, F_SETFL, mode|O_NONBLOCK) == -1) if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed"); fatal("fcntl failed");
cctx->srv_in = buffer_create(BUFSIZ); imsg_init(&cctx->ibuf, fd);
cctx->srv_out = buffer_create(BUFSIZ);
if (cmdflags & CMD_SENDENVIRON)
client_send_environ(cctx);
if (isatty(STDIN_FILENO)) { if (isatty(STDIN_FILENO)) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl(TIOCGWINSZ)"); fatal("ioctl(TIOCGWINSZ)");
data.version = PROTOCOL_VERSION;
data.flags = flags; data.flags = flags;
data.sx = ws.ws_col; data.sx = ws.ws_col;
data.sy = ws.ws_row; data.sy = ws.ws_row;
*data.tty = '\0';
if (getcwd(data.cwd, sizeof data.cwd) == NULL) if (getcwd(data.cwd, sizeof data.cwd) == NULL)
*data.cwd = '\0'; *data.cwd = '\0';
*data.term = '\0';
if ((term = getenv("TERM")) != NULL) {
if (strlcpy(data.term,
term, sizeof data.term) >= sizeof data.term)
*data.term = '\0';
}
*data.tty = '\0';
if ((name = ttyname(STDIN_FILENO)) == NULL) if ((name = ttyname(STDIN_FILENO)) == NULL)
fatal("ttyname failed"); fatal("ttyname failed");
if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty) if (strlcpy(data.tty, name, sizeof data.tty) >= sizeof data.tty)
fatalx("ttyname failed"); fatalx("ttyname failed");
b = buffer_create(BUFSIZ); fd2 = dup(STDIN_FILENO);
cmd_send_string(b, getenv("TERM")); imsg_compose(&cctx->ibuf, MSG_IDENTIFY,
client_write_server2(cctx, MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd2, &data, sizeof data);
&data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b));
buffer_destroy(b);
} }
return (0); return (0);
@@ -134,19 +139,41 @@ not_found:
return (1); return (1);
} }
void
client_send_environ(struct client_ctx *cctx)
{
char **var;
struct msg_environ_data data;
for (var = environ; *var != NULL; var++) {
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
continue;
client_write_server(cctx, MSG_ENVIRON, &data, sizeof data);
}
}
int int
client_main(struct client_ctx *cctx) client_main(struct client_ctx *cctx)
{ {
struct pollfd pfd; struct pollfd pfd;
char *error; int n, nfds;
int xtimeout; /* Yay for ncurses namespace! */
siginit(); siginit();
logfile("client"); logfile("client");
error = NULL; /*
while (!sigterm) { * imsg_read in the first client poll loop (before the terminal has
* been initialiased) may have read messages into the buffer after the
* MSG_READY switched to here. Process anything outstanding now so poll
* doesn't hang waiting for messages that have already arrived.
*/
if (client_msg_dispatch(cctx) != 0)
goto out;
for (;;) {
if (sigterm)
client_write_server(cctx, MSG_EXITING, NULL, 0);
if (sigchld) { if (sigchld) {
waitpid(WAIT_ANY, NULL, WNOHANG); waitpid(WAIT_ANY, NULL, WNOHANG);
sigchld = 0; sigchld = 0;
@@ -159,32 +186,37 @@ client_main(struct client_ctx *cctx)
sigcont = 0; sigcont = 0;
} }
switch (client_msg_dispatch(cctx, &error)) { pfd.fd = cctx->ibuf.fd;
case -1:
goto out;
case 0:
/* May be more in buffer, don't let poll block. */
xtimeout = 0;
break;
default:
/* Out of data, poll may block. */
xtimeout = INFTIM;
break;
}
pfd.fd = cctx->srv_fd;
pfd.events = POLLIN; pfd.events = POLLIN;
if (BUFFER_USED(cctx->srv_out) > 0) if (cctx->ibuf.w.queued > 0)
pfd.events |= POLLOUT; pfd.events |= POLLOUT;
if (poll(&pfd, 1, xtimeout) == -1) { if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
fatal("poll failed"); fatal("poll failed");
} }
if (nfds == 0)
continue;
if (buffer_poll(&pfd, cctx->srv_in, cctx->srv_out) != 0) if (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))
goto server_dead; fatalx("socket error");
if (pfd.revents & POLLIN) {
if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
cctx->exittype = CCTX_DIED;
break;
}
if (client_msg_dispatch(cctx) != 0)
break;
}
if (pfd.revents & POLLOUT) {
if (msgbuf_write(&cctx->ibuf.w) < 0) {
cctx->exittype = CCTX_DIED;
break;
}
}
} }
out: out:
@@ -192,28 +224,27 @@ out:
printf("[terminated]\n"); printf("[terminated]\n");
return (1); return (1);
} }
switch (cctx->exittype) {
if (cctx->flags & CCTX_SHUTDOWN) { case CCTX_DIED:
printf("[lost server]\n");
return (0);
case CCTX_SHUTDOWN:
printf("[server exited]\n"); printf("[server exited]\n");
return (0); return (0);
} case CCTX_EXIT:
if (cctx->errstr != NULL) {
if (cctx->flags & CCTX_EXIT) { printf("[error: %s]\n", cctx->errstr);
return (1);
}
printf("[exited]\n"); printf("[exited]\n");
return (0); return (0);
} case CCTX_DETACH:
if (cctx->flags & CCTX_DETACH) {
printf("[detached]\n"); printf("[detached]\n");
return (0); return (0);
default:
printf("[unknown error]\n");
return (1);
} }
printf("[error: %s]\n", error);
return (1);
server_dead:
printf("[lost server]\n");
return (0);
} }
void void
@@ -231,3 +262,69 @@ client_handle_winch(struct client_ctx *cctx)
sigwinch = 0; sigwinch = 0;
} }
int
client_msg_dispatch(struct client_ctx *cctx)
{
struct imsg imsg;
struct msg_print_data printdata;
ssize_t n, datalen;
for (;;) {
if ((n = imsg_get(&cctx->ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
switch (imsg.hdr.type) {
case MSG_DETACH:
if (datalen != 0)
fatalx("bad MSG_DETACH size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->exittype = CCTX_DETACH;
break;
case MSG_ERROR:
if (datalen != sizeof printdata)
fatalx("bad MSG_ERROR size");
memcpy(&printdata, imsg.data, sizeof printdata);
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
/* Error string used after exit message from server. */
cctx->errstr = xstrdup(printdata.msg);
imsg_free(&imsg);
return (-1);
case MSG_EXIT:
if (datalen != 0)
fatalx("bad MSG_EXIT size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->exittype = CCTX_EXIT;
break;
case MSG_EXITED:
if (datalen != 0)
fatalx("bad MSG_EXITED size");
imsg_free(&imsg);
return (-1);
case MSG_SHUTDOWN:
if (datalen != 0)
fatalx("bad MSG_SHUTDOWN size");
client_write_server(cctx, MSG_EXITING, NULL, 0);
cctx->exittype = CCTX_SHUTDOWN;
break;
case MSG_SUSPEND:
if (datalen != 0)
fatalx("bad MSG_SUSPEND size");
client_suspend();
break;
default:
fatalx("unexpected message");
}
imsg_free(&imsg);
}
}

16
clock.c
View File

@@ -1,4 +1,4 @@
/* $Id: clock.c,v 1.4 2009-05-04 17:58:25 nicm Exp $ */ /* $Id: clock.c,v 1.7 2009-09-11 14:13:52 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -112,8 +112,6 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
strftime(tim, sizeof tim, "%H:%M", localtime(&t)); strftime(tim, sizeof tim, "%H:%M", localtime(&t));
screen_write_clearscreen(ctx); screen_write_clearscreen(ctx);
memcpy(&gc, &grid_default_cell, sizeof gc);
gc.fg = colour;
if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) { if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) { if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
@@ -121,7 +119,8 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
y = screen_size_y(s) / 2; y = screen_size_y(s) / 2;
screen_write_cursormove(ctx, x, y); screen_write_cursormove(ctx, x, y);
gc.fg = colour; memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_fg(&gc, colour);
screen_write_puts(ctx, &gc, "%s", tim); screen_write_puts(ctx, &gc, "%s", tim);
} }
return; return;
@@ -130,6 +129,8 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
x = (screen_size_x(s) / 2) - 3 * strlen(tim); x = (screen_size_x(s) / 2) - 3 * strlen(tim);
y = (screen_size_y(s) / 2) - 3; y = (screen_size_y(s) / 2) - 3;
memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_bg(&gc, colour);
for (ptr = tim; *ptr != '\0'; ptr++) { for (ptr = tim; *ptr != '\0'; ptr++) {
if (*ptr >= '0' && *ptr <= '9') if (*ptr >= '0' && *ptr <= '9')
idx = *ptr - '0'; idx = *ptr - '0';
@@ -147,13 +148,10 @@ clock_draw(struct screen_write_ctx *ctx, u_int colour, int style)
} }
for (j = 0; j < 5; j++) { for (j = 0; j < 5; j++) {
screen_write_cursormove(ctx, x, y + j);
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
screen_write_cursormove(ctx, x + i, y + j);
if (clock_table[idx][j][i]) if (clock_table[idx][j][i])
gc.attr |= GRID_ATTR_REVERSE; screen_write_putc(ctx, &gc, ' ');
else
gc.attr &= ~GRID_ATTR_REVERSE;
screen_write_putc(ctx, &gc, ' ');
} }
} }
x += 6; x += 6;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-attach-session.c,v 1.26 2009-06-25 16:34:50 nicm Exp $ */ /* $Id: cmd-attach-session.c,v 1.32 2009-08-09 17:48:55 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_attach_session_entry = { const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "attach-session", "attach",
"[-d] " CMD_TARGET_SESSION_USAGE, "[-d] " CMD_TARGET_SESSION_USAGE,
CMD_DFLAG|CMD_CANTNEST|CMD_STARTSERVER, CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, CMD_CHFLAG('d'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_attach_session_exec, cmd_attach_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,10 +42,10 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct session *s; struct session *s;
char *cause; struct client *c;
const char *update;
if (ctx->curclient != NULL) char *overrides, *cause;
return (0); u_int i;
if (ARRAY_LENGTH(&sessions) == 0) { if (ARRAY_LENGTH(&sessions) == 0) {
ctx->error(ctx, "no sessions"); ctx->error(ctx, "no sessions");
@@ -56,24 +54,53 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { if (ctx->cmdclient == NULL && ctx->curclient == NULL)
ctx->error(ctx, "not a terminal"); return (0);
return (-1);
if (ctx->cmdclient == NULL) {
if (data->chflags & CMD_CHFLAG('d')) {
/*
* Can't use server_write_session in case attaching to
* the same session as currently attached to.
*/
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
if (c == ctx->curclient)
continue;
server_write_client(c, MSG_DETACH, NULL, 0);
}
}
ctx->curclient->session = s;
server_redraw_client(ctx->curclient);
} else {
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 (data->chflags & CMD_CHFLAG('d'))
server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s;
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);
} }
if (tty_open(&ctx->cmdclient->tty, &cause) != 0) {
ctx->error(ctx, "terminal open failed: %s", cause);
xfree(cause);
return (-1);
}
if (data->flags & CMD_DFLAG)
server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s;
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
recalculate_sizes(); recalculate_sizes();
server_redraw_client(ctx->cmdclient);
return (1); return (1); /* 1 means don't tell command client to exit */
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-bind-key.c,v 1.21 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-bind-key.c,v 1.25 2009-07-28 23:19:06 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -26,26 +28,28 @@
int cmd_bind_key_parse(struct cmd *, int, char **, char **); int cmd_bind_key_parse(struct cmd *, int, char **, char **);
int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *); int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_bind_key_send(struct cmd *, struct buffer *);
void cmd_bind_key_recv(struct cmd *, struct buffer *);
void cmd_bind_key_free(struct cmd *); void cmd_bind_key_free(struct cmd *);
size_t cmd_bind_key_print(struct cmd *, char *, size_t); size_t cmd_bind_key_print(struct cmd *, char *, size_t);
int cmd_bind_key_table(struct cmd *, struct cmd_ctx *);
struct cmd_bind_key_data { struct cmd_bind_key_data {
int key; int key;
int can_repeat; int can_repeat;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
int command_key;
char *tablename;
char *modecmd;
}; };
const struct cmd_entry cmd_bind_key_entry = { const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind", "bind-key", "bind",
"[-r] key command [arguments]", "[-cnr] [-t key-table] key command [arguments]",
0, 0, 0,
NULL, NULL,
cmd_bind_key_parse, cmd_bind_key_parse,
cmd_bind_key_exec, cmd_bind_key_exec,
cmd_bind_key_send,
cmd_bind_key_recv,
cmd_bind_key_free, cmd_bind_key_free,
cmd_bind_key_print cmd_bind_key_print
}; };
@@ -54,17 +58,29 @@ int
cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_bind_key_data *data; struct cmd_bind_key_data *data;
int opt; int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->can_repeat = 0; data->can_repeat = 0;
data->cmdlist = NULL; data->cmdlist = NULL;
data->command_key = 0;
data->tablename = NULL;
data->modecmd = NULL;
while ((opt = getopt(argc, argv, "r")) != -1) { while ((opt = getopt(argc, argv, "cnrt:")) != -1) {
switch (opt) { switch (opt) {
case 'c':
data->command_key = 1;
break;
case 'n':
no_prefix = 1;
break;
case 'r': case 'r':
data->can_repeat = 1; data->can_repeat = 1;
break; break;
case 't':
data->tablename = xstrdup(optarg);
break;
default: default:
goto usage; goto usage;
} }
@@ -78,11 +94,19 @@ cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
xasprintf(cause, "unknown key: %s", argv[0]); xasprintf(cause, "unknown key: %s", argv[0]);
goto error; goto error;
} }
if (!no_prefix)
data->key |= KEYC_PREFIX;
argc--; argc--;
argv++; argv++;
if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL) if (data->tablename != NULL) {
goto error; if (argc != 1)
goto usage;
data->modecmd = xstrdup(argv[0]);
} else {
if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL)
goto error;
}
return (0); return (0);
@@ -101,6 +125,8 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (data->tablename != NULL)
return (cmd_bind_key_table(self, ctx));
key_bindings_add(data->key, data->can_repeat, data->cmdlist); key_bindings_add(data->key, data->can_repeat, data->cmdlist);
data->cmdlist = NULL; /* avoid free */ data->cmdlist = NULL; /* avoid free */
@@ -108,23 +134,37 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
return (0); return (0);
} }
void int
cmd_bind_key_send(struct cmd *self, struct buffer *b) cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_bind_key_data *data = self->data; struct cmd_bind_key_data *data = self->data;
const struct mode_key_table *mtab;
struct mode_key_binding *mbind, mtmp;
enum mode_key_cmd cmd;
buffer_write(b, data, sizeof *data); if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
cmd_list_send(data->cmdlist, b); ctx->error(ctx, "unknown key table: %s", data->tablename);
} return (-1);
}
void cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd);
cmd_bind_key_recv(struct cmd *self, struct buffer *b) if (cmd == MODEKEY_NONE) {
{ ctx->error(ctx, "unknown command: %s", data->modecmd);
struct cmd_bind_key_data *data; return (-1);
}
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data); mtmp.key = data->key & ~KEYC_PREFIX;
data->cmdlist = cmd_list_recv(b); mtmp.mode = data->command_key ? 1 : 0;
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
mbind->cmd = cmd;
return (0);
}
mbind = xmalloc(sizeof *mbind);
mbind->key = mtmp.key;
mbind->mode = mtmp.mode;
mbind->cmd = cmd;
SPLAY_INSERT(mode_key_tree, mtab->tree, mbind);
return (0);
} }
void void
@@ -134,6 +174,10 @@ cmd_bind_key_free(struct cmd *self)
if (data->cmdlist != NULL) if (data->cmdlist != NULL)
cmd_list_free(data->cmdlist); cmd_list_free(data->cmdlist);
if (data->tablename != NULL)
xfree(data->tablename);
if (data->modecmd != NULL)
xfree(data->modecmd);
xfree(data); xfree(data);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-break-pane.c,v 1.3 2009-05-18 21:01:38 nicm Exp $ */ /* $Id: cmd-break-pane.c,v 1.8 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,41 +30,31 @@ int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_break_pane_entry = { const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp", "break-pane", "breakp",
CMD_PANE_WINDOW_USAGE " [-d]", CMD_TARGET_PANE_USAGE " [-d]",
CMD_DFLAG, 0, CMD_CHFLAG('d'),
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_break_pane_exec, cmd_break_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct session *s; struct session *s;
struct window_pane *wp; struct window_pane *wp;
struct window *w; struct window *w;
char *cause; char *cause;
int base_idx;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't break pane: %d", data->pane); ctx->error(ctx, "can't break with only one pane");
return (-1); return (-1);
} }
@@ -74,17 +64,18 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (wl->window->active == NULL) if (wl->window->active == NULL)
wl->window->active = TAILQ_NEXT(wp, entry); wl->window->active = TAILQ_NEXT(wp, entry);
} }
layout_refresh(wl->window, 0); layout_close_pane(wp);
w = wp->window = window_create1(s->sx, s->sy); w = wp->window = window_create1(s->sx, s->sy);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp; w->active = wp;
w->name = default_window_name(w); w->name = default_window_name(w);
layout_init(w);
wl = session_attach(s, w, -1, &cause); /* can't fail */ base_idx = options_get_number(&s->options, "base-index");
if (!(data->flags & CMD_DFLAG)) wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
if (!(data->chflags & CMD_CHFLAG('d')))
session_select(s, wl->idx); session_select(s, wl->idx);
layout_refresh(w, 0);
server_redraw_session(s); server_redraw_session(s);

152
cmd-choose-client.c Normal file
View File

@@ -0,0 +1,152 @@
/* $Id: cmd-choose-client.c,v 1.3 2009-09-07 23:59:19 tcunha Exp $ */
/*
* 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 client.
*/
int cmd_choose_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_client_callback(void *, int);
void cmd_choose_client_free(void *);
const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL,
CMD_TARGET_WINDOW_USAGE " [template]",
CMD_ARG01, 0,
cmd_target_init,
cmd_target_parse,
cmd_choose_client_exec,
cmd_target_free,
cmd_target_print
};
struct cmd_choose_client_data {
struct client *client;
char *template;
};
int
cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct cmd_choose_client_data *cdata;
struct winlink *wl;
struct client *c;
u_int i, idx, cur;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
if (c == ctx->curclient)
cur = idx;
idx++;
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)" : "");
}
cdata = xmalloc(sizeof *cdata);
if (data->arg != NULL)
cdata->template = xstrdup(data->arg);
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, cdata);
return (0);
}
void
cmd_choose_client_callback(void *data, int idx)
{
struct cmd_choose_client_data *cdata = data;
struct client *c;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause;
if (idx == -1)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
if ((u_int) idx > ARRAY_LENGTH(&clients) - 1)
return;
c = ARRAY_ITEM(&clients, idx);
if (c == NULL || c->session == NULL)
return;
template = cmd_template_replace(cdata->template, c->tty.path, 1);
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(void *data)
{
struct cmd_choose_client_data *cdata = data;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-session.c,v 1.7 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-choose-session.c,v 1.13 2009-09-07 23:59:19 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -27,22 +29,22 @@
int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *); int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_session_callback(void *, int); void cmd_choose_session_callback(void *, int);
void cmd_choose_session_free(void *);
const struct cmd_entry cmd_choose_session_entry = { const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL, "choose-session", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE " [template]",
0, CMD_ARG01, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_choose_session_exec, cmd_choose_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
struct cmd_choose_session_data { struct cmd_choose_session_data {
u_int client; struct client *client;
char *template;
}; };
int int
@@ -81,10 +83,15 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->client = server_client_index(ctx->curclient); if (data->arg != NULL)
cdata->template = xstrdup(data->arg);
else
cdata->template = xstrdup("switch-client -t '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready( window_choose_ready(wl->window->active,
wl->window->active, cur, cmd_choose_session_callback, cdata); cur, cmd_choose_session_callback, cmd_choose_session_free, cdata);
return (0); return (0);
} }
@@ -93,15 +100,53 @@ void
cmd_choose_session_callback(void *data, int idx) cmd_choose_session_callback(void *data, int idx)
{ {
struct cmd_choose_session_data *cdata = data; struct cmd_choose_session_data *cdata = data;
struct client *c; struct session *s;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause;
if (idx != -1 && cdata->client <= ARRAY_LENGTH(&clients) - 1) { if (idx == -1)
c = ARRAY_ITEM(&clients, cdata->client); return;
if (c != NULL && (u_int) idx <= ARRAY_LENGTH(&sessions) - 1) { if (cdata->client->flags & CLIENT_DEAD)
c->session = ARRAY_ITEM(&sessions, idx); return;
recalculate_sizes();
server_redraw_client(c); if ((u_int) idx > ARRAY_LENGTH(&sessions) - 1)
return;
s = ARRAY_ITEM(&sessions, 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); xfree(cdata);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-window.c,v 1.9 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-choose-window.c,v 1.17 2009-09-07 23:59:19 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -27,22 +29,23 @@
int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *); int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_window_callback(void *, int); void cmd_choose_window_callback(void *, int);
void cmd_choose_window_free(void *);
const struct cmd_entry cmd_choose_window_entry = { const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL, "choose-window", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE " [template]",
0, CMD_ARG01, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_choose_window_exec, cmd_choose_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
struct cmd_choose_window_data { struct cmd_choose_window_data {
u_int session; struct client *client;
struct session *session;
char *template;
}; };
int int
@@ -54,6 +57,8 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl, *wm; struct winlink *wl, *wm;
struct window *w; struct window *w;
u_int idx, cur; u_int idx, cur;
char flag, *title;
const char *left, *right;
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "must be run interactively");
@@ -75,17 +80,44 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cur = idx; cur = idx;
idx++; idx++;
flag = ' ';
if (session_alert_has(s, wm, WINDOW_ACTIVITY))
flag = '#';
else if (session_alert_has(s, wm, WINDOW_BELL))
flag = '!';
else if (session_alert_has(s, wm, WINDOW_CONTENT))
flag = '+';
else if (wm == s->curw)
flag = '*';
else if (wm == SLIST_FIRST(&s->lastw))
flag = '-';
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, window_choose_add(wl->window->active,
wm->idx, "%3d: %s [%ux%u %s] (%u panes)", wm->idx, w->name, wm->idx, "%3d: %s%c [%ux%u] (%u panes)%s%s%s",
w->sx, w->sy, layout_name(w), window_count_panes(w)); wm->idx, w->name, flag, w->sx, w->sy, window_count_panes(w),
left, title, right);
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
if (session_index(s, &cdata->session) != 0) if (data->arg != NULL)
fatalx("session not found"); cdata->template = xstrdup(data->arg);
else
cdata->template = xstrdup("select-window -t '%%'");
cdata->session = s;
cdata->session->references++;
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready( window_choose_ready(wl->window->active,
wl->window->active, cur, cmd_choose_window_callback, cdata); cur, cmd_choose_window_callback, cmd_choose_window_free, cdata);
return (0); return (0);
} }
@@ -94,13 +126,54 @@ void
cmd_choose_window_callback(void *data, int idx) cmd_choose_window_callback(void *data, int idx)
{ {
struct cmd_choose_window_data *cdata = data; struct cmd_choose_window_data *cdata = data;
struct session *s; struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *target, *template, *cause;
if (idx != -1 && cdata->session <= ARRAY_LENGTH(&sessions) - 1) { if (idx == -1)
s = ARRAY_ITEM(&sessions, cdata->session); return;
if (s != NULL && session_select(s, idx) == 0) if (cdata->client->flags & CLIENT_DEAD)
server_redraw_session(s); return;
recalculate_sizes(); if (cdata->session->flags & SESSION_DEAD)
return;
if (cdata->client->session != cdata->session)
return;
xasprintf(&target, "%s:%d", cdata->session->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); xfree(cdata);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-clear-history.c,v 1.3 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-clear-history.c,v 1.7 2009-07-30 21:04:40 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,36 +28,24 @@ int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clear_history_entry = { const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist", "clear-history", "clearhist",
CMD_PANE_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_clear_history_exec, cmd_clear_history_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
struct grid *gd; struct grid *gd;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
gd = wp->base.grid; gd = wp->base.grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy); grid_move_lines(gd, 0, gd->hsize, gd->sy);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-clock-mode.c,v 1.3 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-clock-mode.c,v 1.6 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clock_mode_entry = { const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL, "clock-mode", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_clock_mode_exec, cmd_clock_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -43,12 +41,12 @@ int
cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
window_pane_set_mode(wl->window->active, &window_clock_mode); window_pane_set_mode(wp, &window_clock_mode);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-command-prompt.c,v 1.16 2009-02-16 18:58:14 nicm Exp $ */ /* $Id: cmd-command-prompt.c,v 1.25 2009-08-25 13:53:39 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,57 +27,111 @@
* Prompt for command in client. * Prompt for command in client.
*/ */
void cmd_command_prompt_init(struct cmd *, int); void cmd_command_prompt_init(struct cmd *, int);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); int cmd_command_prompt_parse(struct cmd *, int, char **, char **);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
void cmd_command_prompt_free(struct cmd *);
size_t cmd_command_prompt_print(struct cmd *, char *, size_t);
int cmd_command_prompt_callback(void *, const char *); int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_cfree(void *);
const struct cmd_entry cmd_command_prompt_entry = { const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL, "command-prompt", NULL,
CMD_TARGET_CLIENT_USAGE " [template]", CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]",
CMD_ARG01, 0, 0,
cmd_command_prompt_init, cmd_command_prompt_init,
cmd_target_parse, cmd_command_prompt_parse,
cmd_command_prompt_exec, cmd_command_prompt_exec,
cmd_target_send, cmd_command_prompt_free,
cmd_target_recv, cmd_command_prompt_print
cmd_target_free,
cmd_target_print
}; };
struct cmd_command_prompt_data { struct cmd_command_prompt_data {
char *prompts;
char *target;
char *template;
};
struct cmd_command_prompt_cdata {
struct client *c; struct client *c;
char *next_prompt;
char *prompts;
char *template; char *template;
int idx;
}; };
void void
cmd_command_prompt_init(struct cmd *self, int key) cmd_command_prompt_init(struct cmd *self, int key)
{ {
struct cmd_target_data *data; struct cmd_command_prompt_data *data;
cmd_target_init(self, key); self->data = data = xmalloc(sizeof *data);
data = self->data; data->prompts = NULL;
data->target = NULL;
data->template = NULL;
switch (key) { switch (key) {
case ',': case ',':
data->arg = xstrdup("rename-window '%%'"); data->template = xstrdup("rename-window '%%'");
break; break;
case '.': case '.':
data->arg = xstrdup("move-window -t '%%'"); data->template = xstrdup("move-window -t '%%'");
break; break;
case 'f': case 'f':
data->arg = xstrdup("find-window '%%'"); data->template = xstrdup("find-window '%%'");
break; break;
} }
} }
int
cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_command_prompt_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "p:t:")) != -1) {
switch (opt) {
case 'p':
if (data->prompts == NULL)
data->prompts = xstrdup(optarg);
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->template = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int int
cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_command_prompt_data *data = self->data;
struct cmd_command_prompt_data *cdata; struct cmd_command_prompt_cdata *cdata;
struct client *c; struct client *c;
char *hdr, *ptr; char *prompt, *ptr;
size_t n;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1); return (-1);
@@ -87,80 +141,102 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->c = c; cdata->c = c;
if (data->arg != NULL) { cdata->idx = 1;
cdata->template = xstrdup(data->arg); cdata->next_prompt = NULL;
if ((ptr = strchr(data->arg, ' ')) == NULL) cdata->prompts = NULL;
ptr = strchr(data->arg, '\0'); cdata->template = NULL;
xasprintf(&hdr, "(%.*s) ", (int) (ptr - data->arg), data->arg);
} else { if (data->template != NULL)
cdata->template = NULL; cdata->template = xstrdup(data->template);
hdr = xstrdup(":"); else
} cdata->template = xstrdup("%1");
status_prompt_set(c, hdr, cmd_command_prompt_callback, cdata, 0); if (data->prompts != NULL)
xfree(hdr); cdata->prompts = xstrdup(data->prompts);
else if (data->template != NULL) {
n = strcspn(data->template, " ,");
xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template);
} else
cdata->prompts = xstrdup(":");
cdata->next_prompt = cdata->prompts;
ptr = strsep(&cdata->next_prompt, ",");
if (data->prompts == NULL)
prompt = xstrdup(ptr);
else
xasprintf(&prompt, "%s ", ptr);
status_prompt_set(c, prompt, cmd_command_prompt_callback,
cmd_command_prompt_cfree, cdata, 0);
xfree(prompt);
return (0); return (0);
} }
void
cmd_command_prompt_free(struct cmd *self)
{
struct cmd_command_prompt_data *data = self->data;
if (data->prompts != NULL)
xfree(data->prompts);
if (data->target != NULL)
xfree(data->target);
if (data->template != NULL)
xfree(data->template);
xfree(data);
}
size_t
cmd_command_prompt_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_command_prompt_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->prompts != NULL)
off += cmd_prarg(buf + off, len - off, " -p ", data->prompts);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->template != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->template);
return (off);
}
int int
cmd_command_prompt_callback(void *data, const char *s) cmd_command_prompt_callback(void *data, const char *s)
{ {
struct cmd_command_prompt_data *cdata = data; struct cmd_command_prompt_cdata *cdata = data;
struct client *c = cdata->c; struct client *c = cdata->c;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx ctx; struct cmd_ctx ctx;
char *cause, *ptr, *buf, ch; char *cause, *newtempl, *prompt, *ptr;
size_t len, slen;
if (s == NULL) { if (s == NULL)
xfree(cdata);
return (0); return (0);
newtempl = cmd_template_replace(cdata->template, s, cdata->idx);
xfree(cdata->template);
cdata->template = newtempl;
if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
xasprintf(&prompt, "%s ", ptr);
status_prompt_update(c, prompt);
xfree(prompt);
cdata->idx++;
return (1);
} }
slen = strlen(s);
len = 0; if (cmd_string_parse(newtempl, &cmdlist, &cause) != 0) {
buf = NULL; if (cause != NULL) {
if (cdata->template != NULL) { *cause = toupper((u_char) *cause);
ptr = cdata->template; status_message_set(c, "%s", cause);
while (*ptr != '\0') { xfree(cause);
switch (ch = *ptr++) {
case '%':
if (*ptr != '%')
break;
ptr++;
buf = xrealloc(buf, 1, len + slen + 1);
memcpy(buf + len, s, slen);
len += slen;
break;
default:
buf = xrealloc(buf, 1, len + 2);
buf[len++] = ch;
break;
}
} }
xfree(cdata->template);
buf[len] = '\0';
s = buf;
}
xfree(cdata);
if (cmd_string_parse(s, &cmdlist, &cause) != 0) {
if (cause == NULL)
return (0);
*cause = toupper((u_char) *cause);
status_message_set(c, cause);
xfree(cause);
cmdlist = NULL;
}
if (buf != NULL)
xfree(buf);
if (cmdlist == NULL)
return (0); return (0);
}
ctx.msgdata = NULL; ctx.msgdata = NULL;
ctx.cursession = c->session;
ctx.curclient = c; ctx.curclient = c;
ctx.error = key_bindings_error; ctx.error = key_bindings_error;
@@ -172,7 +248,19 @@ cmd_command_prompt_callback(void *data, const char *s)
cmd_list_exec(cmdlist, &ctx); cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
if (c->prompt_callback != (void *) &cmd_command_prompt_callback) if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
return (1); return (1);
return (0); return (0);
} }
void
cmd_command_prompt_cfree(void *data)
{
struct cmd_command_prompt_cdata *cdata = data;
if (cdata->prompts != NULL)
xfree(cdata->prompts);
if (cdata->template != NULL)
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-confirm-before.c,v 1.4 2009-04-28 18:29:44 tcunha Exp $ */ /* $Id: cmd-confirm-before.c,v 1.11 2009-08-24 16:24:18 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -29,25 +29,24 @@ int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *);
void cmd_confirm_before_init(struct cmd *, int); void cmd_confirm_before_init(struct cmd *, int);
int cmd_confirm_before_callback(void *, const char *); int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *);
struct cmd_confirm_before_data {
struct client *c;
char *cmd;
};
const struct cmd_entry cmd_confirm_before_entry = { const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm", "confirm-before", "confirm",
CMD_TARGET_CLIENT_USAGE " command", CMD_TARGET_CLIENT_USAGE " command",
CMD_ARG1, CMD_ARG1, 0,
cmd_confirm_before_init, cmd_confirm_before_init,
cmd_target_parse, cmd_target_parse,
cmd_confirm_before_exec, cmd_confirm_before_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
struct cmd_confirm_before_data {
struct client *c;
char *cmd;
};
void void
cmd_confirm_before_init(struct cmd *self, int key) cmd_confirm_before_init(struct cmd *self, int key)
{ {
@@ -67,7 +66,7 @@ cmd_confirm_before_init(struct cmd *self, int key)
} }
int int
cmd_confirm_before_exec(unused struct cmd *self, struct cmd_ctx *ctx) cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct cmd_confirm_before_data *cdata; struct cmd_confirm_before_data *cdata;
@@ -91,8 +90,9 @@ cmd_confirm_before_exec(unused struct cmd *self, struct cmd_ctx *ctx)
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(data->arg); cdata->cmd = xstrdup(data->arg);
cdata->c = c; cdata->c = c;
status_prompt_set( status_prompt_set(cdata->c, buf,
cdata->c, buf, cmd_confirm_before_callback, cdata, PROMPT_SINGLE); cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE);
xfree(buf); xfree(buf);
return (1); return (1);
@@ -107,20 +107,21 @@ cmd_confirm_before_callback(void *data, const char *s)
struct cmd_ctx ctx; struct cmd_ctx ctx;
char *cause; char *cause;
if (s == NULL || tolower((u_char) s[0]) != 'y' || s[1] != '\0') if (s == NULL || *s == '\0')
goto out; return (0);
if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
return (0);
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) { if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) { if (cause != NULL) {
*cause = toupper((u_char) *cause); *cause = toupper((u_char) *cause);
status_message_set(c, cause); status_message_set(c, "%s", cause);
xfree(cause); xfree(cause);
} }
goto out; return (0);
} }
ctx.msgdata = NULL; ctx.msgdata = NULL;
ctx.cursession = c->session;
ctx.curclient = c; ctx.curclient = c;
ctx.error = key_bindings_error; ctx.error = key_bindings_error;
@@ -132,10 +133,15 @@ cmd_confirm_before_callback(void *data, const char *s)
cmd_list_exec(cmdlist, &ctx); cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
out: return (0);
}
void
cmd_confirm_before_free(void *data)
{
struct cmd_confirm_before_data *cdata = data;
if (cdata->cmd != NULL) if (cdata->cmd != NULL)
xfree(cdata->cmd); xfree(cdata->cmd);
xfree(cdata); xfree(cdata);
return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-copy-buffer.c,v 1.1 2009-02-03 17:21:19 tcunha Exp $ */ /* $Id: cmd-copy-buffer.c,v 1.4 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -16,7 +16,10 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -26,8 +29,6 @@
int cmd_copy_buffer_parse(struct cmd *, int, char **, char **); int cmd_copy_buffer_parse(struct cmd *, int, char **, char **);
int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_buffer_send(struct cmd *, struct buffer *);
void cmd_copy_buffer_recv(struct cmd *, struct buffer *);
void cmd_copy_buffer_free(struct cmd *); void cmd_copy_buffer_free(struct cmd *);
void cmd_copy_buffer_init(struct cmd *, int); void cmd_copy_buffer_init(struct cmd *, int);
size_t cmd_copy_buffer_print(struct cmd *, char *, size_t); size_t cmd_copy_buffer_print(struct cmd *, char *, size_t);
@@ -42,12 +43,10 @@ struct cmd_copy_buffer_data {
const struct cmd_entry cmd_copy_buffer_entry = { const struct cmd_entry cmd_copy_buffer_entry = {
"copy-buffer", "copyb", "copy-buffer", "copyb",
"[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]", "[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]",
0, 0, 0,
cmd_copy_buffer_init, cmd_copy_buffer_init,
cmd_copy_buffer_parse, cmd_copy_buffer_parse,
cmd_copy_buffer_exec, cmd_copy_buffer_exec,
cmd_copy_buffer_send,
cmd_copy_buffer_recv,
cmd_copy_buffer_free, cmd_copy_buffer_free,
cmd_copy_buffer_print cmd_copy_buffer_print
}; };
@@ -126,61 +125,44 @@ cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_copy_buffer_data *data = self->data; struct cmd_copy_buffer_data *data = self->data;
struct paste_buffer *pb; struct paste_buffer *pb;
struct paste_stack *dst_ps, *src_ps;
u_char *pdata;
struct session *dst_session, *src_session; struct session *dst_session, *src_session;
u_int limit; u_int limit;
if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL || if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL ||
(src_session = cmd_find_session(ctx, data->src_session)) == NULL) (src_session = cmd_find_session(ctx, data->src_session)) == NULL)
return (-1); return (-1);
dst_ps = &dst_session->buffers;
src_ps = &src_session->buffers;
if (data->src_idx == -1) { if (data->src_idx == -1) {
if ((pb = paste_get_top(&src_session->buffers)) == NULL) { if ((pb = paste_get_top(src_ps)) == NULL) {
ctx->error(ctx, "no buffers"); ctx->error(ctx, "no buffers");
return (-1); return (-1);
} }
} else { } else {
if ((pb = paste_get_index(&src_session->buffers, if ((pb = paste_get_index(src_ps, data->src_idx)) == NULL) {
data->src_idx)) == NULL) {
ctx->error(ctx, "no buffer %d", data->src_idx); ctx->error(ctx, "no buffer %d", data->src_idx);
return (-1); return (-1);
} }
} }
limit = options_get_number(&dst_session->options, "buffer-limit"); limit = options_get_number(&dst_session->options, "buffer-limit");
if (data->dst_idx == -1) {
paste_add(&dst_session->buffers, xstrdup(pb->data), limit); pdata = xmalloc(pb->size);
return (0); memcpy(pdata, pb->data, pb->size);
}
if (paste_replace(&dst_session->buffers, data->dst_idx, if (data->dst_idx == -1)
xstrdup(pb->data)) != 0) { paste_add(dst_ps, pdata, pb->size, limit);
else if (paste_replace(dst_ps, data->dst_idx, pdata, pb->size) != 0) {
ctx->error(ctx, "no buffer %d", data->dst_idx); ctx->error(ctx, "no buffer %d", data->dst_idx);
xfree(pdata);
return (-1); return (-1);
} }
return (0); return (0);
} }
void
cmd_copy_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->dst_session);
cmd_send_string(b, data->src_session);
}
void
cmd_copy_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->dst_session = cmd_recv_string(b);
data->src_session = cmd_recv_string(b);
}
void void
cmd_copy_buffer_free(struct cmd *self) cmd_copy_buffer_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-copy-mode.c,v 1.19 2009-07-01 23:06:32 nicm Exp $ */ /* $Id: cmd-copy-mode.c,v 1.23 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_copy_mode_entry = { const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL, "copy-mode", NULL,
CMD_TARGET_WINDOW_USAGE, "[-u] " CMD_TARGET_PANE_USAGE,
CMD_UFLAG, 0, CMD_CHFLAG('u'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_copy_mode_exec, cmd_copy_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
NULL NULL
}; };
@@ -43,15 +41,13 @@ int
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
wp = wl->window->active;
window_pane_set_mode(wp, &window_copy_mode); window_pane_set_mode(wp, &window_copy_mode);
if (wp->mode == &window_copy_mode && data->flags & CMD_UFLAG) if (wp->mode == &window_copy_mode && data->chflags & CMD_CHFLAG('u'))
window_copy_pageup(wp); window_copy_pageup(wp);
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-delete-buffer.c,v 1.5 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-delete-buffer.c,v 1.7 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_delete_buffer_entry = { const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb", "delete-buffer", "deleteb",
CMD_BUFFER_SESSION_USAGE, CMD_BUFFER_SESSION_USAGE,
0, 0, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_delete_buffer_exec, cmd_delete_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-detach-client.c,v 1.7 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-detach-client.c,v 1.9 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_detach_client_entry = { const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach", "detach-client", "detach",
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_detach_client_exec, cmd_detach_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

63
cmd-display-message.c Normal file
View File

@@ -0,0 +1,63 @@
/* $Id: cmd-display-message.c,v 1.2 2009-07-28 22:12:16 tcunha Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.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 <time.h>
#include "tmux.h"
/*
* Displays a message in the status line.
*/
int cmd_display_message_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_message_entry = {
"display-message", "display",
CMD_TARGET_CLIENT_USAGE " [message]",
CMD_ARG01, 0,
cmd_target_init,
cmd_target_parse,
cmd_display_message_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
const char *template;
char *msg;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
if (data->arg == NULL)
template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)";
else
template = data->arg;
msg = status_replace(c->session, template, time(NULL));
status_message_set(c, "%s", msg);
xfree(msg);
return (0);
}

52
cmd-display-panes.c Normal file
View File

@@ -0,0 +1,52 @@
/* $Id: cmd-display-panes.c,v 1.1 2009-08-31 22:30:15 tcunha Exp $ */
/*
* 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 "tmux.h"
/*
* Display panes on a client.
*/
int cmd_display_panes_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp",
CMD_TARGET_CLIENT_USAGE,
0, 0,
cmd_target_init,
cmd_target_parse,
cmd_display_panes_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
server_set_identify(c);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-down-pane.c,v 1.7 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-down-pane.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_down_pane_entry = { const struct cmd_entry cmd_down_pane_entry = {
"down-pane", "downp", "down-pane", "downp",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_down_pane_exec, cmd_down_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -54,8 +52,8 @@ cmd_down_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
w->active = TAILQ_NEXT(w->active, entry); w->active = TAILQ_NEXT(w->active, entry);
if (w->active == NULL) if (w->active == NULL)
w->active = TAILQ_FIRST(&w->panes); w->active = TAILQ_FIRST(&w->panes);
layout_refresh(w, 1); } while (!window_pane_visible(w->active));
} while (w->active->flags & PANE_HIDDEN); server_status_window(wl->window);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-find-window.c,v 1.10 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-find-window.c,v 1.13 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,12 +34,10 @@ void cmd_find_window_callback(void *, int);
const struct cmd_entry cmd_find_window_entry = { const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw", "find-window", "findw",
CMD_TARGET_WINDOW_USAGE " match-string", CMD_TARGET_WINDOW_USAGE " match-string",
CMD_ARG1, CMD_ARG1, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_find_window_exec, cmd_find_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -140,7 +138,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
fatalx("session not found"); fatalx("session not found");
window_choose_ready( window_choose_ready(
wl->window->active, 0, cmd_find_window_callback, cdata); wl->window->active, 0, cmd_find_window_callback, xfree, cdata);
out: out:
ARRAY_FREE(&list_idx); ARRAY_FREE(&list_idx);
@@ -161,5 +159,4 @@ cmd_find_window_callback(void *data, int idx)
server_redraw_session(s); server_redraw_session(s);
recalculate_sizes(); recalculate_sizes();
} }
xfree(cdata);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-generic.c,v 1.28 2009-05-21 19:47:57 nicm Exp $ */ /* $Id: cmd-generic.c,v 1.34 2009-08-26 22:13:52 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,13 +23,10 @@
#include "tmux.h" #include "tmux.h"
#define CMD_FLAGS "adDgkuU" int cmd_getopt(int, char **, const char *, uint64_t);
#define CMD_FLAGMASK (CMD_AFLAG|CMD_DFLAG|CMD_BIGDFLAG|CMD_GFLAG|CMD_KFLAG| \ int cmd_flags(int, uint64_t, uint64_t *);
CMD_UFLAG|CMD_BIGUFLAG) size_t cmd_print_flags(char *, size_t, size_t, uint64_t);
int cmd_fill_argument(int, char **, char **, int, char **);
int cmd_do_flags(int, int, int *);
size_t cmd_print_flags(char *, size_t, size_t, int);
int cmd_fill_argument(int, char **, int, char **);
size_t size_t
cmd_prarg(char *buf, size_t len, const char *prefix, char *arg) cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
@@ -39,85 +36,78 @@ cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
return (xsnprintf(buf, len, "%s%s", prefix, arg)); return (xsnprintf(buf, len, "%s%s", prefix, arg));
} }
/* Prepend flags from chflags onto flagstr and call getopt. */
int int
cmd_do_flags(int opt, int iflags, int *oflags) cmd_getopt(int argc, char **argv, const char *flagstr, uint64_t chflags)
{ {
switch (opt) { u_char ch;
case 'a': char buf[128];
if (iflags & CMD_AFLAG) { size_t len, off;
(*oflags) |= CMD_AFLAG;
return (0); *buf = '\0';
}
return (-1); len = sizeof buf;
case 'd': off = 0;
if (iflags & CMD_DFLAG) {
(*oflags) |= CMD_DFLAG; for (ch = 0; ch < 26; ch++) {
return (0); if (chflags & CMD_CHFLAG('a' + ch))
} off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
return (-1); if (chflags & CMD_CHFLAG('A' + ch))
case 'D': off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
if (iflags & CMD_BIGDFLAG) {
(*oflags) |= CMD_BIGDFLAG;
return (0);
}
return (-1);
case 'g':
if (iflags & CMD_GFLAG) {
(*oflags) |= CMD_GFLAG;
return (0);
}
return (-1);
case 'k':
if (iflags & CMD_KFLAG) {
(*oflags) |= CMD_KFLAG;
return (0);
}
return (-1);
case 'u':
if (iflags & CMD_UFLAG) {
(*oflags) |= CMD_UFLAG;
return (0);
}
return (-1);
case 'U':
if (iflags & CMD_BIGUFLAG) {
(*oflags) |= CMD_BIGUFLAG;
return (0);
}
return (-1);
} }
return (1);
strlcat(buf, flagstr, sizeof buf);
return (getopt(argc, argv, buf));
} }
size_t /*
cmd_print_flags(char *buf, size_t len, size_t off, int flags) * If this option is expected (in ichflags), set it in ochflags, otherwise
* return -1.
*/
int
cmd_flags(int opt, uint64_t ichflags, uint64_t *ochflags)
{ {
u_char ch;
for (ch = 0; ch < 26; ch++) {
if (opt == 'a' + ch && ichflags & CMD_CHFLAG(opt)) {
(*ochflags) |= CMD_CHFLAG(opt);
return (0);
}
if (opt == 'A' + ch && ichflags & CMD_CHFLAG(opt)) {
(*ochflags) |= CMD_CHFLAG(opt);
return (0);
}
}
return (-1);
}
/* Print the flags supported in chflags. */
size_t
cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags)
{
u_char ch;
size_t boff = off; size_t boff = off;
if ((flags & CMD_FLAGMASK) == 0) if (chflags == 0)
return (0); return (0);
off += xsnprintf(buf + off, len - off, " -"); off += xsnprintf(buf + off, len - off, " -");
if (off < len && flags & CMD_AFLAG)
off += xsnprintf(buf + off, len - off, "a"); for (ch = 0; ch < 26; ch++) {
if (off < len && flags & CMD_BIGDFLAG) if (chflags & CMD_CHFLAG('a' + ch))
off += xsnprintf(buf + off, len - off, "D"); off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
if (off < len && flags & CMD_DFLAG) if (chflags & CMD_CHFLAG('A' + ch))
off += xsnprintf(buf + off, len - off, "d"); off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
if (off < len && flags & CMD_GFLAG) }
off += xsnprintf(buf + off, len - off, "g");
if (off < len && flags & CMD_KFLAG)
off += xsnprintf(buf + off, len - off, "k");
if (off < len && flags & CMD_UFLAG)
off += xsnprintf(buf + off, len - off, "u");
if (off < len && flags & CMD_BIGUFLAG)
off += xsnprintf(buf + off, len - off, "U");
return (off - boff); return (off - boff);
} }
int int
cmd_fill_argument(int flags, char **arg, int argc, char **argv) cmd_fill_argument(int flags, char **arg, char **arg2, int argc, char **argv)
{ {
*arg = NULL; *arg = NULL;
*arg2 = NULL;
if (flags & CMD_ARG1) { if (flags & CMD_ARG1) {
if (argc != 1) if (argc != 1)
@@ -134,6 +124,23 @@ cmd_fill_argument(int flags, char **arg, int argc, char **argv)
return (0); return (0);
} }
if (flags & CMD_ARG2) {
if (argc != 2)
return (-1);
*arg = xstrdup(argv[0]);
*arg2 = xstrdup(argv[1]);
return (0);
}
if (flags & CMD_ARG12) {
if (argc != 1 && argc != 2)
return (-1);
*arg = xstrdup(argv[0]);
if (argc == 2)
*arg2 = xstrdup(argv[1]);
return (0);
}
if (argc != 0) if (argc != 0)
return (-1); return (-1);
return (0); return (0);
@@ -145,28 +152,26 @@ cmd_target_init(struct cmd *self, unused int key)
struct cmd_target_data *data; struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->flags = 0; data->chflags = 0;
data->target = NULL; data->target = NULL;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL;
} }
int int
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_target_data *data; struct cmd_target_data *data;
const struct cmd_entry *entry = self->entry;
int opt; int opt;
/* Don't use the entry version since it may be dependent on key. */ /* Don't use the entry version since it may be dependent on key. */
cmd_target_init(self, 0); cmd_target_init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) { while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
case -1:
goto usage;
case 0:
continue; continue;
}
switch (opt) { switch (opt) {
case 't': case 't':
if (data->target == NULL) if (data->target == NULL)
@@ -179,7 +184,8 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage; goto usage;
return (0); return (0);
@@ -190,27 +196,6 @@ usage:
return (-1); return (-1);
} }
void
cmd_target_send(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_target_recv(struct cmd *self, struct buffer *b)
{
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void void
cmd_target_free(struct cmd *self) cmd_target_free(struct cmd *self)
{ {
@@ -220,6 +205,8 @@ cmd_target_free(struct cmd *self)
xfree(data->target); xfree(data->target);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data); xfree(data);
} }
@@ -232,11 +219,13 @@ cmd_target_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name); off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL) if (data == NULL)
return (off); return (off);
off += cmd_print_flags(buf, len, off, data->flags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->target != NULL) if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target); off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off); return (off);
} }
@@ -246,28 +235,26 @@ cmd_srcdst_init(struct cmd *self, unused int key)
struct cmd_srcdst_data *data; struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->flags = 0; data->chflags = 0;
data->src = NULL; data->src = NULL;
data->dst = NULL; data->dst = NULL;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL;
} }
int int
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_srcdst_data *data; struct cmd_srcdst_data *data;
const struct cmd_entry *entry = self->entry;
int opt; int opt;
cmd_srcdst_init(self, 0); cmd_srcdst_init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) { while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
case -1:
goto usage;
case 0:
continue; continue;
}
switch (opt) { switch (opt) {
case 's': case 's':
if (data->src == NULL) if (data->src == NULL)
@@ -284,7 +271,8 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage; goto usage;
return (0); return (0);
@@ -295,29 +283,6 @@ usage:
return (-1); return (-1);
} }
void
cmd_srcdst_send(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->src);
cmd_send_string(b, data->dst);
cmd_send_string(b, data->arg);
}
void
cmd_srcdst_recv(struct cmd *self, struct buffer *b)
{
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->src = cmd_recv_string(b);
data->dst = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void void
cmd_srcdst_free(struct cmd *self) cmd_srcdst_free(struct cmd *self)
{ {
@@ -329,6 +294,8 @@ cmd_srcdst_free(struct cmd *self)
xfree(data->dst); xfree(data->dst);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data); xfree(data);
} }
@@ -341,13 +308,15 @@ cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name); off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL) if (data == NULL)
return (off); return (off);
off += cmd_print_flags(buf, len, off, data->flags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->src != NULL) if (off < len && data->src != NULL)
off += xsnprintf(buf + off, len - off, " -s %s", data->src); off += xsnprintf(buf + off, len - off, " -s %s", data->src);
if (off < len && data->dst != NULL) if (off < len && data->dst != NULL)
off += xsnprintf(buf + off, len - off, " -t %s", data->dst); off += xsnprintf(buf + off, len - off, " -t %s", data->dst);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off); return (off);
} }
@@ -357,29 +326,27 @@ cmd_buffer_init(struct cmd *self, unused int key)
struct cmd_buffer_data *data; struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->flags = 0; data->chflags = 0;
data->target = NULL; data->target = NULL;
data->buffer = -1; data->buffer = -1;
data->arg = NULL; data->arg = NULL;
data->arg2 = NULL;
} }
int int
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_buffer_data *data; struct cmd_buffer_data *data;
const struct cmd_entry *entry = self->entry;
int opt, n; int opt, n;
const char *errstr; const char *errstr;
cmd_buffer_init(self, 0); cmd_buffer_init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) { while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
case -1:
goto usage;
case 0:
continue; continue;
}
switch (opt) { switch (opt) {
case 'b': case 'b':
if (data->buffer == -1) { if (data->buffer == -1) {
@@ -402,7 +369,8 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage; goto usage;
return (0); return (0);
@@ -414,27 +382,6 @@ error:
return (-1); return (-1);
} }
void
cmd_buffer_send(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_buffer_recv(struct cmd *self, struct buffer *b)
{
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void void
cmd_buffer_free(struct cmd *self) cmd_buffer_free(struct cmd *self)
{ {
@@ -444,6 +391,8 @@ cmd_buffer_free(struct cmd *self)
xfree(data->target); xfree(data->target);
if (data->arg != NULL) if (data->arg != NULL)
xfree(data->arg); xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data); xfree(data);
} }
@@ -456,239 +405,14 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf, len, "%s", self->entry->name); off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL) if (data == NULL)
return (off); return (off);
off += cmd_print_flags(buf, len, off, data->flags); off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->buffer != -1) if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL) if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target); off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL) if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg); off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off); if (off < len && data->arg2 != NULL)
} off += cmd_prarg(buf + off, len - off, " ", data->arg2);
void
cmd_option_init(struct cmd *self, unused int key)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->option = NULL;
data->value = NULL;
}
int
cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_option_data *data;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_option_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc == 2) {
data->option = xstrdup(argv[0]);
data->value = xstrdup(argv[1]);
} else if (argc == 1)
data->option = xstrdup(argv[0]);
else
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_option_send(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->option);
cmd_send_string(b, data->value);
}
void
cmd_option_recv(struct cmd *self, struct buffer *b)
{
struct cmd_option_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->option = cmd_recv_string(b);
data->value = cmd_recv_string(b);
}
void
cmd_option_free(struct cmd *self)
{
struct cmd_option_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->option != NULL)
xfree(data->option);
if (data->value != NULL)
xfree(data->value);
xfree(data);
}
size_t
cmd_option_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_option_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->option != NULL)
off += xsnprintf(buf + off, len - off, " %s", data->option);
if (off < len && data->value != NULL)
off += xsnprintf(buf + off, len - off, " %s", data->value);
return (off);
}
void
cmd_pane_init(struct cmd *self, unused int key)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->flags = 0;
data->target = NULL;
data->arg = NULL;
data->pane = -1;
}
int
cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_pane_data *data;
int opt, n;
const char *errstr;
/* Don't use the entry version since it may be dependent on key. */
cmd_pane_init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, CMD_FLAGS "p:t:")) != -1) {
switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) {
case -1:
goto usage;
case 0:
continue;
}
switch (opt) {
case 'p':
if (data->pane == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "pane %s", errstr);
goto error;
}
data->pane = n;
}
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
void
cmd_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->arg);
}
void
cmd_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->arg = cmd_recv_string(b);
}
void
cmd_pane_free(struct cmd *self)
{
struct cmd_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
xfree(data);
}
size_t
cmd_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->flags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
return (off); return (off);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-has-session.c,v 1.12 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-has-session.c,v 1.14 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_has_session_entry = { const struct cmd_entry cmd_has_session_entry = {
"has-session", "has", "has-session", "has",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_has_session_exec, cmd_has_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

151
cmd-if-shell.c Normal file
View File

@@ -0,0 +1,151 @@
/* $Id: cmd-if-shell.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.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 <errno.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Executes a tmux command if a shell command returns true.
*/
int cmd_if_shell_parse(struct cmd *, int, char **, char **);
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
void cmd_if_shell_free(struct cmd *);
void cmd_if_shell_init(struct cmd *, int);
size_t cmd_if_shell_print(struct cmd *, char *, size_t);
struct cmd_if_shell_data {
char *cmd;
char *sh_cmd;
};
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
"shell-command command",
0, 0,
cmd_if_shell_init,
cmd_if_shell_parse,
cmd_if_shell_exec,
cmd_if_shell_free,
cmd_if_shell_print
};
void
cmd_if_shell_init(struct cmd *self, unused int arg)
{
struct cmd_if_shell_data *data;
self->data = data = xmalloc(sizeof *data);
data->cmd = NULL;
data->sh_cmd = NULL;
}
int
cmd_if_shell_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_if_shell_data *data;
int opt;
self->entry->init(self, 0);
data = self->data;
while ((opt = getopt(argc, argv, "")) != -1) {
switch (opt) {
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 2)
goto usage;
data->sh_cmd = xstrdup(argv[0]);
data->cmd = xstrdup(argv[1]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_if_shell_data *data = self->data;
struct cmd_list *cmdlist;
char *cause;
int ret;
if ((ret = system(data->sh_cmd)) < 0) {
ctx->error(ctx, "system error: %s", strerror(errno));
return (-1);
} else if (ret != 0)
return (0);
if (cmd_string_parse(data->cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) {
ctx->error(ctx, "%s", cause);
xfree(cause);
}
return (-1);
}
if (cmd_list_exec(cmdlist, ctx) < 0) {
cmd_list_free(cmdlist);
return (-1);
}
cmd_list_free(cmdlist);
return (0);
}
void
cmd_if_shell_free(struct cmd *self)
{
struct cmd_if_shell_data *data = self->data;
if (data->cmd != NULL)
xfree(data->cmd);
if (data->sh_cmd != NULL)
xfree(data->sh_cmd);
xfree(data);
}
size_t
cmd_if_shell_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_if_shell_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->sh_cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->sh_cmd);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-pane.c,v 1.7 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-kill-pane.c,v 1.12 2009-07-30 20:45:20 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,43 +30,33 @@ int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_pane_entry = { const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp", "kill-pane", "killp",
CMD_PANE_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_kill_pane_exec, cmd_kill_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {
ctx->error(ctx, "can't kill pane: %d", data->pane); /* Only one pane, kill the window. */
return (-1); server_kill_window(wl->window);
return (0);
} }
layout_close_pane(wp);
window_remove_pane(wl->window, wp); window_remove_pane(wl->window, wp);
server_redraw_window(wl->window); server_redraw_window(wl->window);
layout_refresh(wl->window, 0);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-server.c,v 1.6 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-kill-server.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,13 +32,11 @@ int cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_server_entry = { const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL, "kill-server", NULL,
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_kill_server_exec, cmd_kill_server_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-session.c,v 1.12 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-kill-session.c,v 1.14 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_session_entry = { const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL, "kill-session", NULL,
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_kill_session_exec, cmd_kill_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-window.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-kill-window.c,v 1.19 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_window_entry = { const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw", "kill-window", "killw",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_kill_window_exec, cmd_kill_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,26 +42,11 @@ cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct session *s;
struct client *c;
u_int i;
int destroyed;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
destroyed = session_detach(s, wl); server_kill_window(wl->window);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
continue;
if (destroyed) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
} else
server_redraw_client(c);
}
recalculate_sizes();
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-last-window.c,v 1.16 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-last-window.c,v 1.18 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_last_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_last_window_entry = { const struct cmd_entry cmd_last_window_entry = {
"last-window", "last", "last-window", "last",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_last_window_exec, cmd_last_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-link-window.c,v 1.28 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-link-window.c,v 1.32 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_link_window_entry = { const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw", "link-window", "linkw",
"[-dk] " CMD_SRCDST_WINDOW_USAGE, "[-dk] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG|CMD_KFLAG, 0, CMD_CHFLAG('d')|CMD_CHFLAG('k'),
cmd_srcdst_init, cmd_srcdst_init,
cmd_srcdst_parse, cmd_srcdst_parse,
cmd_link_window_exec, cmd_link_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free, cmd_srcdst_free,
cmd_srcdst_print cmd_srcdst_print
}; };
@@ -52,19 +50,8 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL) if ((wl_src = cmd_find_window(ctx, data->src, NULL)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1); return (-1);
}
if (dst == NULL)
dst = ctx->cursession;
if (dst == NULL)
dst = cmd_current_session(ctx);
if (dst == NULL) {
ctx->error(ctx, "session not found: %s", data->dst);
return (-1);
}
wl_dst = NULL; wl_dst = NULL;
if (idx != -1) if (idx != -1)
@@ -73,7 +60,7 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (wl_dst->window == wl_src->window) if (wl_dst->window == wl_src->window)
return (0); return (0);
if (data->flags & CMD_KFLAG) { if (data->chflags & CMD_CHFLAG('k')) {
/* /*
* Can't use session_detach as it will destroy session * Can't use session_detach as it will destroy session
* if this makes it empty. * if this makes it empty.
@@ -84,12 +71,14 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Force select/redraw if current. */ /* Force select/redraw if current. */
if (wl_dst == dst->curw) { if (wl_dst == dst->curw) {
data->flags &= ~CMD_DFLAG; data->chflags &= ~CMD_CHFLAG('d');
dst->curw = NULL; dst->curw = NULL;
} }
} }
} }
if (idx == -1)
idx = -1 - options_get_number(&dst->options, "base-index");
wl_dst = session_attach(dst, wl_src->window, idx, &cause); wl_dst = session_attach(dst, wl_src->window, idx, &cause);
if (wl_dst == NULL) { if (wl_dst == NULL) {
ctx->error(ctx, "create session failed: %s", cause); ctx->error(ctx, "create session failed: %s", cause);
@@ -97,7 +86,7 @@ cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
if (data->flags & CMD_DFLAG) if (data->chflags & CMD_CHFLAG('d'))
server_status_session(dst); server_status_session(dst);
else { else {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-buffers.c,v 1.7 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-buffers.c,v 1.12 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_buffers_entry = { const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb", "list-buffers", "lsb",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_list_buffers_exec, cmd_list_buffers_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,44 +46,33 @@ cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
u_int idx; u_int idx;
char *tmp; char tmp[51 * 4 + 1];
size_t size, in, out; size_t size, len;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (s->sx > 35) { /* leave three for ... */
size = s->sx - 32;
tmp = xmalloc(size + 1);
} else {
size = 0;
tmp = NULL;
}
idx = 0; idx = 0;
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) {
if (tmp != NULL) { size = pb->size;
in = out = 0;
while (out < size && pb->data[in] != '\0') {
if (pb->data[in] > 31 && pb->data[in] != 127)
tmp[out++] = pb->data[in];
in++;
}
tmp[out] = '\0';
if (out == size) {
tmp[out - 1] = '.';
tmp[out - 2] = '.';
tmp[out - 3] = '.';
}
ctx->print(ctx, "%d: %zu bytes: \"%s\"", /* Translate the first 50 characters. */
idx - 1, strlen(pb->data), tmp); len = size;
} else if (len > 50)
ctx->print(ctx, "%d: %zu bytes", idx, strlen(pb->data)); len = 50;
strvisx(tmp, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
/*
* If the first 50 characterswere encoded as a longer string,
* or there is definitely more data, add "...".
*/
if (size > 50 || strlen(tmp) > 50) {
tmp[50 - 3] = '\0';
strlcat(tmp, "...", sizeof tmp);
}
ctx->print(ctx, "%u: %zu bytes: \"%s\"", idx - 1, size, tmp);
} }
if (tmp != NULL)
xfree(tmp);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-clients.c,v 1.16 2009-06-25 16:34:50 nicm Exp $ */ /* $Id: cmd-list-clients.c,v 1.18 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,13 +32,11 @@ int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_clients_entry = { const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc", "list-clients", "lsc",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_list_clients_exec, cmd_list_clients_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-commands.c,v 1.3 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-commands.c,v 1.5 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_list_commands_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_commands_entry = { const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm", "list-commands", "lscm",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_list_commands_exec, cmd_list_commands_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-keys.c,v 1.14 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-list-keys.c,v 1.20 2009-07-28 23:19:06 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -26,33 +28,97 @@
int cmd_list_keys_exec(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 = { const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk", "list-keys", "lsk",
"", "[-t key-table]",
0, 0, 0,
NULL, cmd_target_init,
NULL, cmd_target_parse,
cmd_list_keys_exec, cmd_list_keys_exec,
NULL, cmd_target_free,
NULL, cmd_target_print
NULL,
NULL
}; };
int int
cmd_list_keys_exec(unused struct cmd *self, struct cmd_ctx *ctx) cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data;
struct key_binding *bd; struct key_binding *bd;
const char *key; const char *key;
char tmp[BUFSIZ]; char tmp[BUFSIZ], keytmp[64];
int width, keywidth;
if (data->target != NULL)
return (cmd_list_keys_table(self, ctx));
width = 0;
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
keywidth = strlen(key) + 1;
if (!(bd->key & KEYC_PREFIX))
keywidth += 2;
if (keywidth > width)
width = keywidth;
}
SPLAY_FOREACH(bd, key_bindings, &key_bindings) { SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
if ((key = key_string_lookup_key(bd->key)) == NULL) key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue; continue;
*tmp = '\0'; *tmp = '\0';
cmd_list_print(bd->cmdlist, tmp, sizeof tmp); cmd_list_print(bd->cmdlist, tmp, sizeof tmp);
ctx->print(ctx, "%11s: %s", key, tmp); if (!(bd->key & KEYC_PREFIX)) {
xsnprintf(keytmp, sizeof keytmp, "[%s]", key);
key = keytmp;
}
ctx->print(ctx, "%*s: %s", width, key, tmp);
}
return (0);
}
int
cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
const struct mode_key_table *mtab;
struct mode_key_binding *mbind;
const char *key, *cmdstr, *mode;
int width, keywidth;
if ((mtab = mode_key_findtable(data->target)) == NULL) {
ctx->error(ctx, "unknown key table: %s", data->target);
return (-1);
}
width = 0;
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
keywidth = strlen(key) + 1;
if (keywidth > width)
width = keywidth;
}
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
mode = "";
if (mbind->mode != 0)
mode = "(command mode) ";
cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
if (cmdstr != NULL)
ctx->print(ctx, "%*s: %s%s", width, key, mode, cmdstr);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-sessions.c,v 1.19 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-list-sessions.c,v 1.21 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,13 +31,11 @@ int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_sessions_entry = { const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls", "", "list-sessions", "ls", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_list_sessions_exec, cmd_list_sessions_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-windows.c,v 1.35 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-list-windows.c,v 1.40 2009-08-09 17:28:23 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_windows_entry = { const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw", "list-windows", "lsw",
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_list_windows_exec, cmd_list_windows_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -50,6 +48,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct grid *gd; struct grid *gd;
struct grid_line *gl;
u_int i; u_int i;
unsigned long long size; unsigned long long size;
const char *name; const char *name;
@@ -67,20 +66,20 @@ cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
size = 0; size = 0;
for (i = 0; i < gd->hsize; i++) { for (i = 0; i < gd->hsize; i++) {
size += gd->size[i] * sizeof **gd->data; gl = &gd->linedata[i];
size += gd->usize[i] * sizeof **gd->udata; size += gl->cellsize * sizeof *gl->celldata;
size += gl->utf8size * sizeof *gl->utf8data;
} }
size += gd->hsize * (sizeof *gd->data); size += gd->hsize * sizeof *gd->linedata;
size += gd->hsize * (sizeof *gd->size);
name = NULL;
if (wp->fd != -1) if (wp->fd != -1)
name = ttyname(wp->fd); name = ttyname(wp->fd);
else if (name == NULL)
name = "unknown"; name = "unknown";
ctx->print(ctx, ctx->print(ctx,
" %s [%ux%u %s] [history %u/%u, %llu bytes]", " %s [%ux%u] [history %u/%u, %llu bytes]",
name, wp->sx, wp->sy, layout_name(w), gd->hsize, name, wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
gd->hlimit, size);
} }
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list.c,v 1.5 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-list.c,v 1.6 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -86,41 +86,6 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_list_send(struct cmd_list *cmdlist, struct buffer *b)
{
struct cmd *cmd;
u_int n;
n = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry)
n++;
buffer_write(b, &n, sizeof n);
TAILQ_FOREACH(cmd, cmdlist, qentry)
cmd_send(cmd, b);
}
struct cmd_list *
cmd_list_recv(struct buffer *b)
{
struct cmd_list *cmdlist;
struct cmd *cmd;
u_int n;
buffer_read(b, &n, sizeof n);
cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist);
while (n-- > 0) {
cmd = cmd_recv(b);
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
}
return (cmdlist);
}
void void
cmd_list_free(struct cmd_list *cmdlist) cmd_list_free(struct cmd_list *cmdlist)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-load-buffer.c,v 1.4 2009-05-21 19:38:51 nicm Exp $ */ /* $Id: cmd-load-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -35,12 +35,10 @@ int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_load_buffer_entry = { const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb", "load-buffer", "loadb",
CMD_BUFFER_SESSION_USAGE " path", CMD_BUFFER_SESSION_USAGE " path",
CMD_ARG1, CMD_ARG1, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_load_buffer_exec, cmd_load_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -50,22 +48,18 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s; struct session *s;
struct stat statbuf; struct stat sb;
FILE *f; FILE *f;
char *buf; u_char *buf;
u_int limit; u_int limit;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (stat(data->arg, &statbuf) < 0) { if (stat(data->arg, &sb) < 0) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
return (-1); return (-1);
} }
if (!S_ISREG(statbuf.st_mode)) {
ctx->error(ctx, "%s: not a regular file", data->arg);
return (-1);
}
if ((f = fopen(data->arg, "rb")) == NULL) { if ((f = fopen(data->arg, "rb")) == NULL) {
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
@@ -76,27 +70,27 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
* We don't want to die due to memory exhaustion, hence xmalloc can't * We don't want to die due to memory exhaustion, hence xmalloc can't
* be used here. * be used here.
*/ */
if ((buf = malloc(statbuf.st_size + 1)) == NULL) { if ((buf = malloc(sb.st_size + 1)) == NULL) {
ctx->error(ctx, "malloc error: %s", strerror(errno)); ctx->error(ctx, "malloc error: %s", strerror(errno));
fclose(f);
return (-1); return (-1);
} }
if (fread(buf, 1, statbuf.st_size, f) != (size_t) statbuf.st_size) { if (fread(buf, 1, sb.st_size, f) != (size_t) sb.st_size) {
ctx->error(ctx, "%s: fread error", data->arg); ctx->error(ctx, "%s: fread error", data->arg);
xfree(buf); xfree(buf);
fclose(f); fclose(f);
return (-1); return (-1);
} }
buf[statbuf.st_size] = '\0';
fclose(f); fclose(f);
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&s->options, "buffer-limit");
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&s->buffers, buf, limit); paste_add(&s->buffers, buf, sb.st_size, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, buf) != 0) { if (paste_replace(&s->buffers, data->buffer, buf, sb.st_size) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
xfree(buf); xfree(buf);
return (-1); return (-1);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-lock-server.c,v 1.4 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-lock-server.c,v 1.6 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,14 +33,12 @@ int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_lock_server_entry = { const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock", "lock-server", "lock",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_lock_server_exec, cmd_lock_server_exec,
NULL, NULL,
NULL, NULL,
NULL,
NULL,
}; };
int int

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-move-window.c,v 1.5 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-move-window.c,v 1.9 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_move_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_move_window_entry = { const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew", "move-window", "movew",
"[-dk] " CMD_SRCDST_WINDOW_USAGE, "[-dk] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG|CMD_KFLAG, 0, CMD_CHFLAG('d')|CMD_CHFLAG('k'),
cmd_srcdst_init, cmd_srcdst_init,
cmd_srcdst_parse, cmd_srcdst_parse,
cmd_move_window_exec, cmd_move_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free, cmd_srcdst_free,
cmd_srcdst_print cmd_srcdst_print
}; };
@@ -54,19 +52,8 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL) if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
if (arg_parse_window(data->dst, &dst, &idx) != 0) {
ctx->error(ctx, "bad window: %s", data->dst);
return (-1); return (-1);
}
if (dst == NULL)
dst = ctx->cursession;
if (dst == NULL)
dst = cmd_current_session(ctx);
if (dst == NULL) {
ctx->error(ctx, "session not found: %s", data->dst);
return (-1);
}
wl_dst = NULL; wl_dst = NULL;
if (idx != -1) if (idx != -1)
@@ -75,7 +62,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (wl_dst->window == wl_src->window) if (wl_dst->window == wl_src->window)
return (0); return (0);
if (data->flags & CMD_KFLAG) { if (data->chflags & CMD_CHFLAG('k')) {
/* /*
* Can't use session_detach as it will destroy session * Can't use session_detach as it will destroy session
* if this makes it empty. * if this makes it empty.
@@ -86,12 +73,14 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Force select/redraw if current. */ /* Force select/redraw if current. */
if (wl_dst == dst->curw) { if (wl_dst == dst->curw) {
data->flags &= ~CMD_DFLAG; data->chflags &= ~CMD_CHFLAG('d');
dst->curw = NULL; dst->curw = NULL;
} }
} }
} }
if (idx == -1)
idx = -1 - options_get_number(&dst->options, "base-index");
wl_dst = session_attach(dst, wl_src->window, idx, &cause); wl_dst = session_attach(dst, wl_src->window, idx, &cause);
if (wl_dst == NULL) { if (wl_dst == NULL) {
ctx->error(ctx, "attach window failed: %s", cause); ctx->error(ctx, "attach window failed: %s", cause);
@@ -111,7 +100,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_client(c); server_redraw_client(c);
} }
if (data->flags & CMD_DFLAG) if (data->chflags & CMD_CHFLAG('d'))
server_status_session(dst); server_status_session(dst);
else { else {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-new-session.c,v 1.41 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-new-session.c,v 1.66 2009-09-16 12:36:27 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,10 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -26,8 +30,6 @@
int cmd_new_session_parse(struct cmd *, int, char **, char **); int cmd_new_session_parse(struct cmd *, int, char **, char **);
int cmd_new_session_exec(struct cmd *, struct cmd_ctx *); int cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_session_send(struct cmd *, struct buffer *);
void cmd_new_session_recv(struct cmd *, struct buffer *);
void cmd_new_session_free(struct cmd *); void cmd_new_session_free(struct cmd *);
void cmd_new_session_init(struct cmd *, int); void cmd_new_session_init(struct cmd *, int);
size_t cmd_new_session_print(struct cmd *, char *, size_t); size_t cmd_new_session_print(struct cmd *, char *, size_t);
@@ -42,12 +44,10 @@ struct cmd_new_session_data {
const struct cmd_entry cmd_new_session_entry = { const struct cmd_entry cmd_new_session_entry = {
"new-session", "new", "new-session", "new",
"[-d] [-n window-name] [-s session-name] [command]", "[-d] [-n window-name] [-s session-name] [command]",
CMD_STARTSERVER|CMD_CANTNEST, CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, 0,
cmd_new_session_init, cmd_new_session_init,
cmd_new_session_parse, cmd_new_session_parse,
cmd_new_session_exec, cmd_new_session_exec,
cmd_new_session_send,
cmd_new_session_recv,
cmd_new_session_free, cmd_new_session_free,
cmd_new_session_print cmd_new_session_print
}; };
@@ -111,106 +111,149 @@ int
cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_new_session_data *data = self->data; struct cmd_new_session_data *data = self->data;
struct client *c = ctx->cmdclient;
struct session *s; struct session *s;
char *cmd, *cwd, *cause; struct window *w;
struct environ env;
struct termios tio, *tiop;
const char *update;
char *overrides, *cmd, *cwd, *cause;
int detached, idx;
u_int sx, sy; u_int sx, sy;
if (ctx->curclient != NULL)
return (0);
if (!data->flag_detached) {
if (c == NULL) {
ctx->error(ctx, "no client to attach to");
return (-1);
}
if (!(c->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal");
return (-1);
}
}
if (data->newname != NULL && session_find(data->newname) != NULL) { if (data->newname != NULL && session_find(data->newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", data->newname); ctx->error(ctx, "duplicate session: %s", data->newname);
return (-1); return (-1);
} }
cmd = data->cmd; /*
if (cmd == NULL) * There are three cases:
cmd = options_get_string(&global_options, "default-command"); *
if (c == NULL || c->cwd == NULL) * 1. If cmdclient is non-NULL, new-session has been called from the
cwd = options_get_string(&global_options, "default-path"); * command-line - cmdclient is to become a new attached, interactive
* client. Unless -d is given, the terminal must be opened and then
* the client sent MSG_READY.
*
* 2. If cmdclient is NULL, new-session has been called from an
* existing client (such as a key binding).
*
* 3. Both are NULL, the command was in the configuration file. Treat
* this as if -d was given even if it was not.
*
* In all cases, a new additional session needs to be created and
* (unless -d) set as the current session for the client.
*/
/* Set -d if no client. */
detached = data->flag_detached;
if (ctx->cmdclient == NULL && ctx->curclient == NULL)
detached = 1;
/*
* Save the termios settings, part of which is used for new windows in
* this session.
*
* This is read again with tcgetattr() rather than using tty.tio as if
* detached, tty_open won't be called. Because of this, it must be done
* before opening the terminal as that calls tcsetattr() to prepare for
* tmux taking over.
*/
if (ctx->cmdclient != NULL && ctx->cmdclient->tty.fd != -1) {
if (tcgetattr(ctx->cmdclient->tty.fd, &tio) != 0)
fatal("tcgetattr failed");
tiop = &tio;
} else
tiop = NULL;
/* Open the terminal if necessary. */
if (!detached && ctx->cmdclient != NULL) {
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);
xfree(cause);
return (-1);
}
}
/* Get the new session working directory. */
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd;
else else
cwd = c->cwd; cwd = options_get_string(&global_s_options, "default-path");
sx = 80; /* Find new session size. */
sy = 25; if (detached) {
if (!data->flag_detached) { sx = 80;
sx = c->tty.sx; sy = 24;
sy = c->tty.sy; } 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--;
if (sx == 0)
sx = 1;
if (sy == 0)
sy = 1;
if (options_get_number(&global_options, "status")) { /* Figure out the command for the new window. */
if (sy == 0) if (data->cmd != NULL)
sy = 1; cmd = data->cmd;
else else
sy--; cmd = options_get_string(&global_s_options, "default-command");
}
if (!data->flag_detached && tty_open(&c->tty, &cause) != 0) { /* Construct the environment. */
ctx->error(ctx, "open terminal failed: %s", cause); environ_init(&env);
xfree(cause); update = options_get_string(&global_s_options, "update-environment");
return (-1); if (ctx->cmdclient != NULL)
} environ_update(update, &ctx->cmdclient->environ, &env);
/* Create the new session. */
s = session_create(data->newname, cmd, cwd, sx, sy, &cause); idx = -1 - options_get_number(&global_s_options, "base-index");
s = session_create(
data->newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
if (s == NULL) { if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause); ctx->error(ctx, "create session failed: %s", cause);
xfree(cause); xfree(cause);
return (-1); return (-1);
} }
environ_free(&env);
/* Set the initial window name if one given. */
if (data->winname != NULL) { if (data->winname != NULL) {
xfree(s->curw->window->name); w = s->curw->window;
s->curw->window->name = xstrdup(data->winname);
options_set_number( xfree(w->name);
&s->curw->window->options, "automatic-rename", 0); w->name = xstrdup(data->winname);
options_set_number(&w->options, "automatic-rename", 0);
} }
if (data->flag_detached) { /*
if (c != NULL) * Set the client to the new session. If a command client exists, it is
server_write_client(c, MSG_EXIT, NULL, 0); * taking this session and needs to get MSG_READY and stay around.
} else { */
c->session = s; if (!detached) {
server_write_client(c, MSG_READY, NULL, 0); if (ctx->cmdclient != NULL) {
server_redraw_client(c); server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
ctx->cmdclient->session = s;
server_redraw_client(ctx->cmdclient);
} else {
ctx->curclient->session = s;
server_redraw_client(ctx->curclient);
}
} }
recalculate_sizes(); recalculate_sizes();
return (1); return (!detached); /* 1 means don't tell command client to exit */
}
void
cmd_new_session_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->newname);
cmd_send_string(b, data->winname);
cmd_send_string(b, data->cmd);
}
void
cmd_new_session_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_session_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->newname = cmd_recv_string(b);
data->winname = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
} }
void void

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-new-window.c,v 1.31 2009-01-23 16:59:14 nicm Exp $ */ /* $Id: cmd-new-window.c,v 1.37 2009-08-16 19:16:27 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,8 +28,6 @@
int cmd_new_window_parse(struct cmd *, int, char **, char **); int cmd_new_window_parse(struct cmd *, int, char **, char **);
int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_window_send(struct cmd *, struct buffer *);
void cmd_new_window_recv(struct cmd *, struct buffer *);
void cmd_new_window_free(struct cmd *); void cmd_new_window_free(struct cmd *);
void cmd_new_window_init(struct cmd *, int); void cmd_new_window_init(struct cmd *, int);
size_t cmd_new_window_print(struct cmd *, char *, size_t); size_t cmd_new_window_print(struct cmd *, char *, size_t);
@@ -45,12 +43,10 @@ struct cmd_new_window_data {
const struct cmd_entry cmd_new_window_entry = { const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww", "new-window", "neww",
"[-dk] [-n window-name] [-t target-window] [command]", "[-dk] [-n window-name] [-t target-window] [command]",
0, 0, 0,
cmd_new_window_init, cmd_new_window_init,
cmd_new_window_parse, cmd_new_window_parse,
cmd_new_window_exec, cmd_new_window_exec,
cmd_new_window_send,
cmd_new_window_recv,
cmd_new_window_free, cmd_new_window_free,
cmd_new_window_print cmd_new_window_print
}; };
@@ -126,18 +122,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (arg_parse_window(data->target, &s, &idx) != 0) { if ((idx = cmd_find_index(ctx, data->target, &s)) == -2)
ctx->error(ctx, "bad window: %s", data->target);
return (-1); return (-1);
}
if (s == NULL)
s = ctx->cursession;
if (s == NULL)
s = cmd_current_session(ctx);
if (s == NULL) {
ctx->error(ctx, "session not found: %s", data->target);
return (-1);
}
wl = NULL; wl = NULL;
if (idx != -1) if (idx != -1)
@@ -164,10 +150,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (cmd == NULL) if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL) if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&global_options, "default-path"); cwd = options_get_string(&s->options, "default-path");
else else
cwd = ctx->cmdclient->cwd; cwd = ctx->cmdclient->cwd;
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, data->name, cmd, cwd, idx, &cause); wl = session_new(s, data->name, cmd, cwd, idx, &cause);
if (wl == NULL) { if (wl == NULL) {
ctx->error(ctx, "create window failed: %s", cause); ctx->error(ctx, "create window failed: %s", cause);
@@ -183,29 +171,6 @@ cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_new_window_send(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
cmd_send_string(b, data->name);
cmd_send_string(b, data->cmd);
}
void
cmd_new_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_new_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->name = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
}
void void
cmd_new_window_free(struct cmd *self) cmd_new_window_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-next-layout.c,v 1.2 2009-04-30 21:17:06 nicm Exp $ */ /* $Id: cmd-next-layout.c,v 1.5 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_next_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_layout_entry = { const struct cmd_entry cmd_next_layout_entry = {
"next-layout", "nextl", "next-layout", "nextl",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_next_layout_exec, cmd_next_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,12 +42,13 @@ cmd_next_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
u_int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
layout_next(wl->window); layout = layout_set_next(wl->window);
ctx->info(ctx, "layout now: %s", layout_name(wl->window)); ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-next-window.c,v 1.17 2009-06-25 15:29:34 nicm Exp $ */ /* $Id: cmd-next-window.c,v 1.20 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,12 +30,10 @@ int cmd_next_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_window_entry = { const struct cmd_entry cmd_next_window_entry = {
"next-window", "next", "next-window", "next",
"[-a] " CMD_TARGET_SESSION_USAGE, "[-a] " CMD_TARGET_SESSION_USAGE,
CMD_AFLAG, 0, CMD_CHFLAG('a'),
cmd_next_window_init, cmd_next_window_init,
cmd_target_parse, cmd_target_parse,
cmd_next_window_exec, cmd_next_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,8 +46,8 @@ cmd_next_window_init(struct cmd *self, int key)
cmd_target_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDESC('n')) if (key == ('n' | KEYC_ESCAPE))
data->flags |= CMD_AFLAG; data->chflags |= CMD_CHFLAG('a');
} }
int int
@@ -63,7 +61,7 @@ cmd_next_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
activity = 0; activity = 0;
if (data->flags & CMD_AFLAG) if (data->chflags & CMD_CHFLAG('a'))
activity = 1; activity = 1;
if (session_next(s, activity) == 0) if (session_next(s, activity) == 0)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-paste-buffer.c,v 1.16 2009-07-02 16:23:54 nicm Exp $ */ /* $Id: cmd-paste-buffer.c,v 1.20 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,16 +27,15 @@
*/ */
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_paste_buffer_lf2cr(struct buffer *, const char *, size_t);
const struct cmd_entry cmd_paste_buffer_entry = { const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb", "paste-buffer", "pasteb",
"[-d] " CMD_BUFFER_WINDOW_USAGE, "[-dr] " CMD_BUFFER_WINDOW_USAGE,
CMD_DFLAG, 0, CMD_CHFLAG('d')|CMD_CHFLAG('r'),
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_paste_buffer_exec, cmd_paste_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -46,13 +45,13 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window_pane *wp;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
w = wl->window; wp = wl->window->active;
if (data->buffer == -1) if (data->buffer == -1)
pb = paste_get_top(&s->buffers); pb = paste_get_top(&s->buffers);
@@ -63,11 +62,16 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
} }
if (pb != NULL && *pb->data != '\0') if (pb != NULL && *pb->data != '\0') {
buffer_write(w->active->out, pb->data, strlen(pb->data)); /* -r means raw data without LF->CR conversion. */
if (data->chflags & CMD_CHFLAG('r'))
buffer_write(wp->out, pb->data, pb->size);
else
cmd_paste_buffer_lf2cr(wp->out, pb->data, pb->size);
}
/* Delete the buffer if -d. */ /* Delete the buffer if -d. */
if (data->flags & CMD_DFLAG) { if (data->chflags & CMD_CHFLAG('d')) {
if (data->buffer == -1) if (data->buffer == -1)
paste_free_top(&s->buffers); paste_free_top(&s->buffers);
else else
@@ -76,3 +80,21 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
/* Add bytes to a buffer but change every '\n' to '\r'. */
void
cmd_paste_buffer_lf2cr(struct buffer *b, const char *data, size_t size)
{
const char *end = data + size;
const char *lf;
while ((lf = memchr(data, '\n', end - data)) != NULL) {
if (lf != data)
buffer_write(b, data, lf - data);
buffer_write8(b, '\r');
data = lf + 1;
}
if (end != data)
buffer_write(b, data, end - data);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-previous-layout.c,v 1.1 2009-04-30 21:17:06 nicm Exp $ */ /* $Id: cmd-previous-layout.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_previous_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_layout_entry = { const struct cmd_entry cmd_previous_layout_entry = {
"previous-layout", "prevl", "previous-layout", "prevl",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_previous_layout_exec, cmd_previous_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,12 +42,13 @@ cmd_previous_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
u_int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
layout_previous(wl->window); layout = layout_set_previous(wl->window);
ctx->info(ctx, "layout now: %s", layout_name(wl->window)); ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-previous-window.c,v 1.17 2009-06-25 15:29:34 nicm Exp $ */ /* $Id: cmd-previous-window.c,v 1.20 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,12 +30,10 @@ int cmd_previous_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_window_entry = { const struct cmd_entry cmd_previous_window_entry = {
"previous-window", "prev", "previous-window", "prev",
"[-a] " CMD_TARGET_SESSION_USAGE, "[-a] " CMD_TARGET_SESSION_USAGE,
CMD_AFLAG, 0, CMD_CHFLAG('a'),
cmd_previous_window_init, cmd_previous_window_init,
cmd_target_parse, cmd_target_parse,
cmd_previous_window_exec, cmd_previous_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,8 +46,8 @@ cmd_previous_window_init(struct cmd *self, int key)
cmd_target_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDESC('p')) if (key == ('p' | KEYC_ESCAPE))
data->flags |= CMD_AFLAG; data->chflags |= CMD_CHFLAG('a');
} }
int int
@@ -63,7 +61,7 @@ cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
activity = 0; activity = 0;
if (data->flags & CMD_AFLAG) if (data->chflags & CMD_CHFLAG('a'))
activity = 1; activity = 1;
if (session_previous(s, activity) == 0) if (session_previous(s, activity) == 0)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-refresh-client.c,v 1.8 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-refresh-client.c,v 1.10 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_refresh_client_entry = { const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh", "refresh-client", "refresh",
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_refresh_client_exec, cmd_refresh_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rename-session.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-rename-session.c,v 1.18 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_session_entry = { const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename", "rename-session", "rename",
CMD_TARGET_SESSION_USAGE " new-name", CMD_TARGET_SESSION_USAGE " new-name",
CMD_ARG1, CMD_ARG1, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_rename_session_exec, cmd_rename_session_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -53,5 +51,7 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
xfree(s->name); xfree(s->name);
s->name = xstrdup(data->arg); s->name = xstrdup(data->arg);
server_status_session(s);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rename-window.c,v 1.27 2009-05-04 17:58:26 nicm Exp $ */ /* $Id: cmd-rename-window.c,v 1.29 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_window_entry = { const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew", "rename-window", "renamew",
CMD_TARGET_WINDOW_USAGE " new-name", CMD_TARGET_WINDOW_USAGE " new-name",
CMD_ARG1, CMD_ARG1, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_rename_window_exec, cmd_rename_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-resize-pane.c,v 1.7 2009-05-21 19:46:00 nicm Exp $ */ /* $Id: cmd-resize-pane.c,v 1.12 2009-07-30 20:45:20 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,32 +31,47 @@ int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_entry = { const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep", "resize-pane", "resizep",
CMD_PANE_WINDOW_USAGE "[-DU] [adjustment]", "[-DU] " CMD_TARGET_PANE_USAGE " [adjustment]",
CMD_ARG01|CMD_BIGUFLAG|CMD_BIGDFLAG, CMD_ARG01,
CMD_CHFLAG('D')|CMD_CHFLAG('L')|CMD_CHFLAG('R')|CMD_CHFLAG('U'),
cmd_resize_pane_init, cmd_resize_pane_init,
cmd_pane_parse, cmd_target_parse,
cmd_resize_pane_exec, cmd_resize_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
void void
cmd_resize_pane_init(struct cmd *self, int key) cmd_resize_pane_init(struct cmd *self, int key)
{ {
struct cmd_pane_data *data; struct cmd_target_data *data;
cmd_pane_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDCTL(KEYC_DOWN)) if (key == (KEYC_UP | KEYC_CTRL))
data->flags |= CMD_BIGDFLAG; data->chflags |= CMD_CHFLAG('U');
if (key == (KEYC_DOWN | KEYC_CTRL))
if (key == KEYC_ADDESC(KEYC_UP)) data->chflags |= CMD_CHFLAG('D');
if (key == (KEYC_LEFT | KEYC_CTRL))
data->chflags |= CMD_CHFLAG('L');
if (key == (KEYC_RIGHT | KEYC_CTRL))
data->chflags |= CMD_CHFLAG('R');
if (key == (KEYC_UP | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('U');
data->arg = xstrdup("5"); data->arg = xstrdup("5");
if (key == KEYC_ADDESC(KEYC_DOWN)) { }
data->flags |= CMD_BIGDFLAG; if (key == (KEYC_DOWN | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('D');
data->arg = xstrdup("5");
}
if (key == (KEYC_LEFT | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('L');
data->arg = xstrdup("5");
}
if (key == (KEYC_RIGHT | KEYC_ESCAPE)) {
data->chflags |= CMD_CHFLAG('R');
data->arg = xstrdup("5"); data->arg = xstrdup("5");
} }
} }
@@ -64,23 +79,14 @@ cmd_resize_pane_init(struct cmd *self, int key)
int int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
const char *errstr; const char *errstr;
struct window_pane *wp; struct window_pane *wp;
u_int adjust; u_int adjust;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (data->arg == NULL) if (data->arg == NULL)
adjust = 1; adjust = 1;
@@ -92,12 +98,14 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
} }
if (!(data->flags & CMD_BIGDFLAG)) if (data->chflags & (CMD_CHFLAG('L')|CMD_CHFLAG('R'))) {
adjust = -adjust; if (data->chflags & CMD_CHFLAG('L'))
if (layout_resize(wp, adjust) != 0) { adjust = -adjust;
ctx->error(ctx, "layout %s " layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust);
"does not support resizing", layout_name(wp->window)); } else {
return (-1); if (data->chflags & CMD_CHFLAG('U'))
adjust = -adjust;
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
} }
server_redraw_window(wl->window); server_redraw_window(wl->window);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-respawn-window.c,v 1.14 2009-03-04 17:24:07 nicm Exp $ */ /* $Id: cmd-respawn-window.c,v 1.22 2009-09-16 12:36:27 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_window_entry = { const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw", "respawn-window", "respawnw",
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]", "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
CMD_ARG01|CMD_KFLAG, CMD_ARG01, CMD_CHFLAG('k'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_respawn_window_exec, cmd_respawn_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,14 +47,14 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct session *s; struct session *s;
const char **env; struct environ env;
char *cause; char *cause;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
if (!(data->flags & CMD_KFLAG)) { if (!(data->chflags & CMD_CHFLAG('k'))) {
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1) if (wp->fd == -1)
continue; continue;
@@ -66,22 +64,31 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
} }
env = server_fill_environ(s); environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
layout_free(w);
window_destroy_panes(w); window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
window_pane_resize(wp, w->sx, w->sy); window_pane_resize(wp, w->sx, w->sy);
if (window_pane_spawn(wp, data->arg, NULL, env, &cause) != 0) { if (window_pane_spawn(
wp, data->arg, NULL, NULL, &env, s->tio, &cause) != 0) {
ctx->error(ctx, "respawn window failed: %s", cause); ctx->error(ctx, "respawn window failed: %s", cause);
xfree(cause); xfree(cause);
environ_free(&env);
return (-1); return (-1);
} }
layout_init(w);
screen_reinit(&wp->base); screen_reinit(&wp->base);
window_set_active_pane(w, wp);
recalculate_sizes(); recalculate_sizes();
server_redraw_window(w); server_redraw_window(w);
environ_free(&env);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rotate-window.c,v 1.4 2009-06-25 15:28:08 nicm Exp $ */ /* $Id: cmd-rotate-window.c,v 1.9 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,12 +30,10 @@ int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rotate_window_entry = { const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew", "rotate-window", "rotatew",
"[-DU] " CMD_TARGET_WINDOW_USAGE, "[-DU] " CMD_TARGET_WINDOW_USAGE,
CMD_BIGUFLAG|CMD_BIGDFLAG, 0, CMD_CHFLAG('D')|CMD_CHFLAG('U'),
cmd_rotate_window_init, cmd_rotate_window_init,
cmd_target_parse, cmd_target_parse,
cmd_rotate_window_exec, cmd_rotate_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -48,8 +46,8 @@ cmd_rotate_window_init(struct cmd *self, int key)
cmd_target_init(self, key); cmd_target_init(self, key);
data = self->data; data = self->data;
if (key == KEYC_ADDESC('o')) if (key == ('o' | KEYC_ESCAPE))
data->flags |= CMD_BIGDFLAG; data->chflags |= CMD_CHFLAG('D');
} }
int int
@@ -59,64 +57,68 @@ cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp, *wp2; struct window_pane *wp, *wp2;
struct layout_cell *lc;
u_int sx, sy, xoff, yoff; u_int sx, sy, xoff, yoff;
int flags;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
if (data->flags & CMD_BIGDFLAG) { if (data->chflags & CMD_CHFLAG('D')) {
wp = TAILQ_LAST(&w->panes, window_panes); wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
lc = wp->layout_cell;
xoff = wp->xoff; yoff = wp->yoff; xoff = wp->xoff; yoff = wp->yoff;
sx = wp->sx; sy = wp->sy; sx = wp->sx; sy = wp->sy;
flags = wp->flags;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if ((wp2 = TAILQ_NEXT(wp, entry)) == NULL) if ((wp2 = TAILQ_NEXT(wp, entry)) == NULL)
break; break;
wp->layout_cell = wp2->layout_cell;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = wp2->xoff; wp->yoff = wp2->yoff; wp->xoff = wp2->xoff; wp->yoff = wp2->yoff;
wp->flags &= ~PANE_HIDDEN;
wp->flags |= wp2->flags & PANE_HIDDEN;
window_pane_resize(wp, wp2->sx, wp2->sy); window_pane_resize(wp, wp2->sx, wp2->sy);
} }
wp->layout_cell = lc;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = xoff; wp->yoff = yoff; wp->xoff = xoff; wp->yoff = yoff;
wp->flags &= ~PANE_HIDDEN;
wp->flags |= flags & PANE_HIDDEN;
window_pane_resize(wp, sx, sy); window_pane_resize(wp, sx, sy);
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL) if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
wp = TAILQ_LAST(&w->panes, window_panes); wp = TAILQ_LAST(&w->panes, window_panes);
window_set_active_pane(w, wp); window_set_active_pane(w, wp);
server_redraw_window(w);
} else { } else {
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_TAIL(&w->panes, wp, entry); TAILQ_INSERT_TAIL(&w->panes, wp, entry);
lc = wp->layout_cell;
xoff = wp->xoff; yoff = wp->yoff; xoff = wp->xoff; yoff = wp->yoff;
sx = wp->sx; sy = wp->sy; sx = wp->sx; sy = wp->sy;
flags = wp->flags;
TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) { TAILQ_FOREACH_REVERSE(wp, &w->panes, window_panes, entry) {
if ((wp2 = TAILQ_PREV(wp, window_panes, entry)) == NULL) if ((wp2 = TAILQ_PREV(wp, window_panes, entry)) == NULL)
break; break;
wp->layout_cell = wp2->layout_cell;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = wp2->xoff; wp->yoff = wp2->yoff; wp->xoff = wp2->xoff; wp->yoff = wp2->yoff;
wp->flags &= ~PANE_HIDDEN;
wp->flags |= wp2->flags & PANE_HIDDEN;
window_pane_resize(wp, wp2->sx, wp2->sy); window_pane_resize(wp, wp2->sx, wp2->sy);
} }
wp->layout_cell = lc;
if (wp->layout_cell != NULL)
wp->layout_cell->wp = wp;
wp->xoff = xoff; wp->yoff = yoff; wp->xoff = xoff; wp->yoff = yoff;
wp->flags &= ~PANE_HIDDEN;
wp->flags |= flags & PANE_HIDDEN;
window_pane_resize(wp, sx, sy); window_pane_resize(wp, sx, sy);
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL) if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
window_set_active_pane(w, wp); window_set_active_pane(w, wp);
server_redraw_window(w);
} }
layout_refresh(w, 0);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-save-buffer.c,v 1.5 2009-05-18 16:22:30 nicm Exp $ */ /* $Id: cmd-save-buffer.c,v 1.8 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -33,12 +33,10 @@ int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_save_buffer_entry = { const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb", "save-buffer", "saveb",
"[-a] " CMD_BUFFER_SESSION_USAGE " path", "[-a] " CMD_BUFFER_SESSION_USAGE " path",
CMD_AFLAG|CMD_ARG1, CMD_ARG1, CMD_CHFLAG('a'),
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_save_buffer_exec, cmd_save_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -68,7 +66,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
mask = umask(S_IRWXG | S_IRWXO); mask = umask(S_IRWXG | S_IRWXO);
if (data->flags & CMD_AFLAG) if (data->chflags & CMD_CHFLAG('a'))
f = fopen(data->arg, "ab"); f = fopen(data->arg, "ab");
else else
f = fopen(data->arg, "wb"); f = fopen(data->arg, "wb");
@@ -77,7 +75,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
if (fwrite(pb->data, 1, strlen(pb->data), f) != strlen(pb->data)) { if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
ctx->error(ctx, "%s: fwrite error", data->arg); ctx->error(ctx, "%s: fwrite error", data->arg);
fclose(f); fclose(f);
return (-1); return (-1);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-scroll-mode.c,v 1.19 2009-07-01 23:06:32 nicm Exp $ */ /* $Id: cmd-scroll-mode.c,v 1.23 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_scroll_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_scroll_mode_entry = { const struct cmd_entry cmd_scroll_mode_entry = {
"scroll-mode", NULL, "scroll-mode", NULL,
CMD_TARGET_WINDOW_USAGE, "[-u] " CMD_TARGET_PANE_USAGE,
CMD_UFLAG, 0, CMD_CHFLAG('u'),
cmd_scroll_mode_init, cmd_scroll_mode_init,
cmd_target_parse, cmd_target_parse,
cmd_scroll_mode_exec, cmd_scroll_mode_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -50,7 +48,7 @@ cmd_scroll_mode_init(struct cmd *self, int key)
switch (key) { switch (key) {
case KEYC_PPAGE: case KEYC_PPAGE:
data->flags |= CMD_UFLAG; data->chflags |= CMD_CHFLAG('u');
break; break;
} }
} }
@@ -59,15 +57,13 @@ int
cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_scroll_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
wp = wl->window->active;
window_pane_set_mode(wp, &window_scroll_mode); window_pane_set_mode(wp, &window_scroll_mode);
if (wp->mode == &window_scroll_mode && data->flags & CMD_UFLAG) if (wp->mode == &window_scroll_mode && data->chflags & CMD_CHFLAG('u'))
window_scroll_pageup(wp); window_scroll_pageup(wp);
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-layout.c,v 1.3 2009-06-25 16:34:50 nicm Exp $ */ /* $Id: cmd-select-layout.c,v 1.8 2009-07-28 23:04:29 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_layout_entry = { const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl", "select-layout", "selectl",
CMD_TARGET_WINDOW_USAGE " layout-name", CMD_TARGET_WINDOW_USAGE " [layout-name]",
CMD_ARG1, CMD_ARG01, 0,
cmd_select_layout_init, cmd_select_layout_init,
cmd_target_parse, cmd_target_parse,
cmd_select_layout_exec, cmd_select_layout_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,17 +47,17 @@ cmd_select_layout_init(struct cmd *self, int key)
data = self->data; data = self->data;
switch (key) { switch (key) {
case KEYC_ADDESC('0'): case ('1' | KEYC_ESCAPE):
data->arg = xstrdup("manual-vertical");
break;
case KEYC_ADDESC('1'):
data->arg = xstrdup("even-horizontal"); data->arg = xstrdup("even-horizontal");
break; break;
case KEYC_ADDESC('2'): case ('2' | KEYC_ESCAPE):
data->arg = xstrdup("even-vertical"); data->arg = xstrdup("even-vertical");
break;
case ('3' | KEYC_ESCAPE):
data->arg = xstrdup("main-horizontal");
break; break;
case KEYC_ADDESC('9'): case ('4' | KEYC_ESCAPE):
data->arg = xstrdup("active-only"); data->arg = xstrdup("main-vertical");
break; break;
} }
} }
@@ -74,13 +72,17 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
if ((layout = layout_lookup(data->arg)) == -1) { if (data->arg == NULL) {
ctx->error(ctx, "unknown or ambiguous layout: %s", data->arg); layout = wl->window->lastlayout;
if (layout == -1)
return (0);
} else if ((layout = layout_set_lookup(data->arg)) == -1) {
ctx->error(ctx, "unknown layout or ambiguous: %s", data->arg);
return (-1); return (-1);
} }
if (layout_select(wl->window, layout) == 0) layout = layout_set_select(wl->window, layout);
ctx->info(ctx, "layout now: %s", layout_name(wl->window)); ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-pane.c,v 1.4 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-select-pane.c,v 1.10 2009-07-30 20:45:20 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,42 +28,31 @@ int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = { const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp", "select-pane", "selectp",
CMD_PANE_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_pane_init, cmd_target_init,
cmd_pane_parse, cmd_target_parse,
cmd_select_pane_exec, cmd_select_pane_exec,
cmd_pane_send, cmd_target_free,
cmd_pane_recv, cmd_target_print
cmd_pane_free,
cmd_pane_print
}; };
int int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_pane_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1); return (-1);
if (data->pane == -1)
wp = wl->window->active;
else {
wp = window_pane_at_index(wl->window, data->pane);
if (wp == NULL) {
ctx->error(ctx, "no pane: %d", data->pane);
return (-1);
}
}
if (wp->flags & PANE_HIDDEN) { if (!window_pane_visible(wp)) {
ctx->error(ctx, "pane %d is hidden", data->pane); ctx->error(ctx, "pane not visible: %s", data->target);
return (-1); return (-1);
} }
window_set_active_pane(wl->window, wp); window_set_active_pane(wl->window, wp);
layout_refresh(wl->window, 1); server_status_window(wl->window);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-prompt.c,v 1.7 2009-02-13 18:57:55 nicm Exp $ */ /* $Id: cmd-select-prompt.c,v 1.12 2009-08-16 19:29:24 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,12 +33,10 @@ int cmd_select_prompt_callback(void *, const char *);
const struct cmd_entry cmd_select_prompt_entry = { const struct cmd_entry cmd_select_prompt_entry = {
"select-prompt", NULL, "select-prompt", NULL,
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_select_prompt_exec, cmd_select_prompt_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -55,7 +53,7 @@ cmd_select_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
if (c->prompt_string != NULL) if (c->prompt_string != NULL)
return (0); return (0);
status_prompt_set(c, "index ", cmd_select_prompt_callback, c, 0); status_prompt_set(c, "index ", cmd_select_prompt_callback, NULL, c, 0);
return (0); return (0);
} }
@@ -68,20 +66,20 @@ cmd_select_prompt_callback(void *data, const char *s)
char msg[128]; char msg[128];
u_int idx; u_int idx;
if (s == NULL) if (s == NULL || *s == '\0')
return (0); return (0);
idx = strtonum(s, 0, UINT_MAX, &errstr); idx = strtonum(s, 0, UINT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s); xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s);
status_message_set(c, msg); status_message_set(c, "%s", msg);
return (0); return (0);
} }
if (winlink_find_by_index(&c->session->windows, idx) == NULL) { if (winlink_find_by_index(&c->session->windows, idx) == NULL) {
xsnprintf(msg, sizeof msg, xsnprintf(msg, sizeof msg,
"Window not found: %s:%d", c->session->name, idx); "Window not found: %s:%d", c->session->name, idx);
status_message_set(c, msg); status_message_set(c, "%s", msg);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-window.c,v 1.21 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-select-window.c,v 1.23 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_window_entry = { const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw", "select-window", "selectw",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_select_window_init, cmd_select_window_init,
cmd_target_parse, cmd_target_parse,
cmd_select_window_exec, cmd_select_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-send-keys.c,v 1.18 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-send-keys.c,v 1.21 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,8 +28,6 @@
int cmd_send_keys_parse(struct cmd *, int, char **, char **); int cmd_send_keys_parse(struct cmd *, int, char **, char **);
int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *); int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
void cmd_send_keys_send(struct cmd *, struct buffer *);
void cmd_send_keys_recv(struct cmd *, struct buffer *);
void cmd_send_keys_free(struct cmd *); void cmd_send_keys_free(struct cmd *);
size_t cmd_send_keys_print(struct cmd *, char *, size_t); size_t cmd_send_keys_print(struct cmd *, char *, size_t);
@@ -42,13 +40,11 @@ struct cmd_send_keys_data {
const struct cmd_entry cmd_send_keys_entry = { const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send", "send-keys", "send",
"[-t target-window] key ...", "[-t target-pane] key ...",
0, 0, 0,
NULL, NULL,
cmd_send_keys_parse, cmd_send_keys_parse,
cmd_send_keys_exec, cmd_send_keys_exec,
cmd_send_keys_send,
cmd_send_keys_recv,
cmd_send_keys_free, cmd_send_keys_free,
cmd_send_keys_print cmd_send_keys_print
}; };
@@ -110,45 +106,21 @@ int
cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_send_keys_data *data = self->data; struct cmd_send_keys_data *data = self->data;
struct winlink *wl; struct window_pane *wp;
u_int i; u_int i;
if (data == NULL) if (data == NULL)
return (-1); return (-1);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
return (-1); return (-1);
for (i = 0; i < data->nkeys; i++) { for (i = 0; i < data->nkeys; i++)
window_pane_key( window_pane_key(wp, ctx->curclient, data->keys[i]);
wl->window->active, ctx->curclient, data->keys[i]);
}
return (0); return (0);
} }
void
cmd_send_keys_send(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
buffer_write(b, data->keys, data->nkeys * sizeof *data->keys);
}
void
cmd_send_keys_recv(struct cmd *self, struct buffer *b)
{
struct cmd_send_keys_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->keys = xcalloc(data->nkeys, sizeof *data->keys);
buffer_read(b, data->keys, data->nkeys * sizeof *data->keys);
}
void void
cmd_send_keys_free(struct cmd *self) cmd_send_keys_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-send-prefix.c,v 1.23 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-send-prefix.c,v 1.26 2009-08-20 11:37:46 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_prefix_entry = { const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL, "send-prefix", NULL,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_PANE_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_send_prefix_exec, cmd_send_prefix_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -44,14 +42,14 @@ cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct cmd_target_data *data = self->data;
struct session *s; struct session *s;
struct winlink *wl; struct window_pane *wp;
int key; int key;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
return (-1); return (-1);
key = options_get_number(&s->options, "prefix"); key = options_get_number(&s->options, "prefix");
window_pane_key(wl->window->active, ctx->curclient, key); window_pane_key(wp, ctx->curclient, key);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-server-info.c,v 1.20 2009-06-25 20:27:31 nicm Exp $ */ /* $Id: cmd-server-info.c,v 1.28 2009-09-07 23:59:19 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -35,13 +35,11 @@ int cmd_server_info_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_server_info_entry = { const struct cmd_entry cmd_server_info_entry = {
"server-info", "info", "server-info", "info",
"", "",
0, 0, 0,
NULL, NULL,
NULL, NULL,
cmd_server_info_exec, cmd_server_info_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };
@@ -58,6 +56,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
struct tty_term_code_entry *ent; struct tty_term_code_entry *ent;
struct utsname un; struct utsname un;
struct grid *gd; struct grid *gd;
struct grid_line *gl;
u_int i, j, k; u_int i, j, k;
char out[80]; char out[80];
char *tim; char *tim;
@@ -69,8 +68,9 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, ctx->print(ctx,
"tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim); "tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim);
ctx->print(ctx, "socket path %s, debug level %d%s", ctx->print(ctx, "socket path %s, debug level %d%s%s",
socket_path, debug_level, be_quiet ? ", quiet" : ""); socket_path, debug_level, be_quiet ? ", quiet" : "",
login_shell ? ", login shell" : "");
if (uname(&un) == 0) { if (uname(&un) == 0) {
ctx->print(ctx, "system is %s %s %s %s", ctx->print(ctx, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine); un.sysname, un.release, un.version, un.machine);
@@ -82,7 +82,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION); ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION);
ctx->print(ctx, "%u clients, %u sessions", ctx->print(ctx, "%u clients, %u sessions",
ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions)); ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions));
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Clients:"); ctx->print(ctx, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@@ -91,11 +91,12 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
continue; continue;
ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] " ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] "
"[flags=0x%x/0x%x]", i, c->tty.path, c->fd, c->tty.fd, "[flags=0x%x/0x%x, references=%u]", i, c->tty.path,
c->session->name, c->tty.sx, c->tty.sy, c->tty.termname, c->ibuf.fd, c->tty.fd, c->session->name,
c->flags, c->tty.flags); c->tty.sx, c->tty.sy, c->tty.termname, c->flags,
c->tty.flags, c->references);
} }
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Sessions: [%zu/%zu]", ctx->print(ctx, "Sessions: [%zu/%zu]",
sizeof (struct grid_cell), sizeof (struct grid_utf8)); sizeof (struct grid_cell), sizeof (struct grid_utf8));
@@ -109,28 +110,30 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] " ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x]", i, s->name, winlink_count(&s->windows), "[flags=0x%x, references=%u]", i, s->name,
tim, s->sx, s->sy, s->flags); winlink_count(&s->windows), tim, s->sx, s->sy, s->flags,
s->references);
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window; w = wl->window;
ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, " ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
"references=%u, layout=%u]", wl->idx, w->name, "references=%u, last layout=%d]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references, w->sx, w->sy, w->flags, w->references,
w->layout); w->lastlayout);
j = 0; j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
lines = ulines = size = usize = 0; lines = ulines = size = usize = 0;
gd = wp->base.grid; gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) { for (k = 0; k < gd->hsize + gd->sy; k++) {
if (gd->data[k] != NULL) { gl = &gd->linedata[k];
if (gl->celldata != NULL) {
lines++; lines++;
size += gd->size[k] * size += gl->cellsize *
sizeof (**gd->data); sizeof *gl->celldata;
} }
if (gd->udata[k] != NULL) { if (gl->utf8data != NULL) {
ulines++; ulines++;
usize += gd->usize[k] * usize += gl->utf8size *
sizeof (**gd->udata); sizeof *gl->utf8data;
} }
} }
ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu " ctx->print(ctx, "%6u: %s %lu %d %u/%u, %zu "
@@ -142,7 +145,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
} }
} }
} }
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Terminals:"); ctx->print(ctx, "Terminals:");
SLIST_FOREACH(term, &tty_terms, entry) { SLIST_FOREACH(term, &tty_terms, entry) {
@@ -174,7 +177,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
} }
} }
} }
ctx->print(ctx, ""); ctx->print(ctx, "%s", "");
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-buffer.c,v 1.7 2009-01-25 18:51:28 tcunha Exp $ */ /* $Id: cmd-set-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,7 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -31,12 +31,10 @@ int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_buffer_entry = { const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb", "set-buffer", "setb",
CMD_BUFFER_SESSION_USAGE " data", CMD_BUFFER_SESSION_USAGE " data",
CMD_ARG1, CMD_ARG1, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_set_buffer_exec, cmd_set_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -47,17 +45,23 @@ cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s; struct session *s;
u_int limit; u_int limit;
u_char *pdata;
size_t psize;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&s->options, "buffer-limit");
pdata = xstrdup(data->arg);
psize = strlen(pdata);
if (data->buffer == -1) { if (data->buffer == -1) {
paste_add(&s->buffers, xstrdup(data->arg), limit); paste_add(&s->buffers, pdata, psize, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, xstrdup(data->arg)) != 0) { if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
xfree(pdata);
return (-1); return (-1);
} }
return (0); return (0);

88
cmd-set-environment.c Normal file
View File

@@ -0,0 +1,88 @@
/* $Id: cmd-set-environment.c,v 1.2 2009-08-11 14:42:59 nicm Exp $ */
/*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Set an environment variable.
*/
int cmd_set_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv",
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
CMD_ARG12, CMD_CHFLAG('g')|CMD_CHFLAG('r')|CMD_CHFLAG('u'),
NULL,
cmd_target_parse,
cmd_set_environment_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct environ *env;
if (*data->arg == '\0') {
ctx->error(ctx, "empty variable name");
return (-1);
}
if (strchr(data->arg, '=') != NULL) {
ctx->error(ctx, "variable name contains =");
return (-1);
}
if (data->chflags & CMD_CHFLAG('g'))
env = &global_environ;
else {
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
env = &s->environ;
}
if (data->chflags & CMD_CHFLAG('u')) {
if (data->arg2 != NULL) {
ctx->error(ctx, "can't specify a value with -u");
return (-1);
}
environ_unset(env, data->arg);
} else if (data->chflags & CMD_CHFLAG('r')) {
if (data->arg2 != NULL) {
ctx->error(ctx, "can't specify a value with -r");
return (-1);
}
environ_set(env, data->arg, NULL);
} else {
if (data->arg2 == NULL) {
ctx->error(ctx, "no value specified");
return (-1);
}
environ_set(env, data->arg, data->arg2);
}
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.62 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-set-option.c,v 1.79 2009-09-19 18:53:01 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,28 +31,34 @@ int cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_option_entry = { const struct cmd_entry cmd_set_option_entry = {
"set-option", "set", "set-option", "set",
CMD_OPTION_SESSION_USAGE, "[-agu] " CMD_TARGET_SESSION_USAGE " option [value]",
CMD_GFLAG|CMD_UFLAG, CMD_ARG12, CMD_CHFLAG('a')|CMD_CHFLAG('g')|CMD_CHFLAG('u'),
NULL, NULL,
cmd_option_parse, cmd_target_parse,
cmd_set_option_exec, cmd_set_option_exec,
cmd_option_send, cmd_target_free,
cmd_option_recv, cmd_target_print
cmd_option_free,
cmd_option_print
}; };
const char *set_option_status_keys_list[] = { const char *set_option_status_keys_list[] = {
"emacs", "vi", NULL "emacs", "vi", NULL
}; };
const char *set_option_status_justify_list[] = {
"left", "centre", "right", NULL
};
const char *set_option_bell_action_list[] = { const char *set_option_bell_action_list[] = {
"none", "any", "current", NULL "none", "any", "current", NULL
}; };
const struct set_option_entry set_option_table[NSETOPTION] = { const struct set_option_entry set_option_table[] = {
{ "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list }, { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list },
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "default-command", SET_OPTION_STRING, 0, 0, NULL }, { "default-command", SET_OPTION_STRING, 0, 0, NULL },
{ "default-path", SET_OPTION_STRING, 0, 0, NULL }, { "default-path", SET_OPTION_STRING, 0, 0, NULL },
{ "default-shell", SET_OPTION_STRING, 0, 0, NULL },
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
@@ -63,69 +69,83 @@ const struct set_option_entry set_option_table[NSETOPTION] = {
{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, { "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL }, { "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles-string", SET_OPTION_STRING, 0, 0, NULL },
{ "status", SET_OPTION_FLAG, 0, 0, NULL }, { "status", SET_OPTION_FLAG, 0, 0, NULL },
{ "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "status-justify",
SET_OPTION_CHOICE, 0, 0, set_option_status_justify_list },
{ "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list }, { "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list },
{ "status-left", SET_OPTION_STRING, 0, 0, NULL }, { "status-left", SET_OPTION_STRING, 0, 0, NULL },
{ "status-left-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-left-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-left-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-right", SET_OPTION_STRING, 0, 0, NULL }, { "status-right", SET_OPTION_STRING, 0, 0, NULL },
{ "status-right-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-right-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-right-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-utf8", SET_OPTION_FLAG, 0, 0, NULL }, { "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
{ "update-environment", SET_OPTION_STRING, 0, 0, NULL },
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL }
}; };
int int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_option_data *data = self->data; struct cmd_target_data *data = self->data;
struct session *s; struct session *s;
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry, *opt;
u_int i; u_int i;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_options; oo = &global_s_options;
else { else {
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
oo = &s->options; oo = &s->options;
} }
if (*data->option == '\0') { if (*data->arg == '\0') {
ctx->error(ctx, "invalid option"); ctx->error(ctx, "invalid option");
return (-1); return (-1);
} }
entry = NULL; entry = NULL;
for (i = 0; i < NSETOPTION; i++) { for (opt = set_option_table; opt->name != NULL; opt++) {
if (strncmp(set_option_table[i].name, if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
data->option, strlen(data->option)) != 0)
continue; continue;
if (entry != NULL) { if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->option); ctx->error(ctx, "ambiguous option: %s", data->arg);
return (-1); return (-1);
} }
entry = &set_option_table[i]; entry = opt;
/* Bail now if an exact match. */ /* Bail now if an exact match. */
if (strcmp(entry->name, data->option) == 0) if (strcmp(entry->name, data->arg) == 0)
break; break;
} }
if (entry == NULL) { if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->option); ctx->error(ctx, "unknown option: %s", data->arg);
return (-1); return (-1);
} }
if (data->flags & CMD_UFLAG) { if (data->chflags & CMD_CHFLAG('u')) {
if (data->flags & CMD_GFLAG) { if (data->chflags & CMD_CHFLAG('g')) {
ctx->error(ctx, ctx->error(ctx,
"can't unset global option: %s", entry->name); "can't unset global option: %s", entry->name);
return (-1); return (-1);
} }
if (data->value != NULL) { if (data->arg2 != NULL) {
ctx->error(ctx, ctx->error(ctx,
"value passed to unset option: %s", entry->name); "value passed to unset option: %s", entry->name);
return (-1); return (-1);
@@ -136,25 +156,26 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
} else { } else {
switch (entry->type) { switch (entry->type) {
case SET_OPTION_STRING: case SET_OPTION_STRING:
set_option_string(ctx, oo, entry, data->value); set_option_string(ctx, oo, entry,
data->arg2, data->chflags & CMD_CHFLAG('a'));
break; break;
case SET_OPTION_NUMBER: case SET_OPTION_NUMBER:
set_option_number(ctx, oo, entry, data->value); set_option_number(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_KEY: case SET_OPTION_KEY:
set_option_key(ctx, oo, entry, data->value); set_option_key(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_COLOUR: case SET_OPTION_COLOUR:
set_option_colour(ctx, oo, entry, data->value); set_option_colour(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_ATTRIBUTES: case SET_OPTION_ATTRIBUTES:
set_option_attributes(ctx, oo, entry, data->value); set_option_attributes(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_FLAG: case SET_OPTION_FLAG:
set_option_flag(ctx, oo, entry, data->value); set_option_flag(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_CHOICE: case SET_OPTION_CHOICE:
set_option_choice(ctx, oo, entry, data->value); set_option_choice(ctx, oo, entry, data->arg2);
break; break;
} }
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-password.c,v 1.5 2009-06-25 16:47:00 nicm Exp $ */ /* $Id: cmd-set-password.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,8 +29,6 @@
int cmd_set_password_parse(struct cmd *, int, char **, char **); int cmd_set_password_parse(struct cmd *, int, char **, char **);
int cmd_set_password_exec(struct cmd *, struct cmd_ctx *); int cmd_set_password_exec(struct cmd *, struct cmd_ctx *);
void cmd_set_password_send(struct cmd *, struct buffer *);
void cmd_set_password_recv(struct cmd *, struct buffer *);
void cmd_set_password_free(struct cmd *); void cmd_set_password_free(struct cmd *);
void cmd_set_password_init(struct cmd *, int); void cmd_set_password_init(struct cmd *, int);
size_t cmd_set_password_print(struct cmd *, char *, size_t); size_t cmd_set_password_print(struct cmd *, char *, size_t);
@@ -43,12 +41,10 @@ struct cmd_set_password_data {
const struct cmd_entry cmd_set_password_entry = { const struct cmd_entry cmd_set_password_entry = {
"set-password", "pass", "set-password", "pass",
"[-c] password", "[-c] password",
0, 0, 0,
cmd_set_password_init, cmd_set_password_init,
cmd_set_password_parse, cmd_set_password_parse,
cmd_set_password_exec, cmd_set_password_exec,
cmd_set_password_send,
cmd_set_password_recv,
cmd_set_password_free, cmd_set_password_free,
cmd_set_password_print cmd_set_password_print
}; };
@@ -118,30 +114,10 @@ cmd_set_password_exec(struct cmd *self, struct cmd_ctx *ctx)
server_password = NULL; server_password = NULL;
else else
server_password = xstrdup(data->password); server_password = xstrdup(data->password);
log_debug("pw now %s", server_password);
return (0); return (0);
} }
void
cmd_set_password_send(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->password);
}
void
cmd_set_password_recv(struct cmd *self, struct buffer *b)
{
struct cmd_set_password_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->password = cmd_recv_string(b);
}
void void
cmd_set_password_free(struct cmd *self) cmd_set_password_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-window-option.c,v 1.28 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-set-window-option.c,v 1.38 2009-08-11 14:42:59 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,15 +31,13 @@ int cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_window_option_entry = { const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw", "set-window-option", "setw",
CMD_OPTION_WINDOW_USAGE, "[-agu] " CMD_TARGET_WINDOW_USAGE " option [value]",
CMD_GFLAG|CMD_UFLAG, CMD_ARG12, CMD_CHFLAG('a')|CMD_CHFLAG('g')|CMD_CHFLAG('u'),
NULL, NULL,
cmd_option_parse, cmd_target_parse,
cmd_set_window_option_exec, cmd_set_window_option_exec,
cmd_option_send, cmd_target_free,
cmd_option_recv, cmd_target_print
cmd_option_free,
cmd_option_print
}; };
const char *set_option_mode_keys_list[] = { const char *set_option_mode_keys_list[] = {
@@ -48,7 +46,7 @@ const char *set_option_mode_keys_list[] = {
const char *set_option_clock_mode_style_list[] = { const char *set_option_clock_mode_style_list[] = {
"12", "24", NULL "12", "24", NULL
}; };
const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = { const struct set_option_entry set_window_option_table[] = {
{ "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL }, { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL },
{ "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL }, { "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL },
{ "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL }, { "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL },
@@ -56,71 +54,76 @@ const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = {
SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list }, SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list },
{ "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "main-pane-height", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list }, { "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list },
{ "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL }, { "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-content", SET_OPTION_STRING, 0, 0, NULL }, { "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, { "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL }, { "utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, { "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL }, { "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL }
}; };
int int
cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_option_data *data = self->data; struct cmd_target_data *data = self->data;
struct winlink *wl; struct winlink *wl;
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry, *opt;
u_int i; u_int i;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_window_options; oo = &global_w_options;
else { else {
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
oo = &wl->window->options; oo = &wl->window->options;
} }
if (*data->option == '\0') { if (*data->arg == '\0') {
ctx->error(ctx, "invalid option"); ctx->error(ctx, "invalid option");
return (-1); return (-1);
} }
entry = NULL; entry = NULL;
for (i = 0; i < NSETWINDOWOPTION; i++) { for (opt = set_window_option_table; opt->name != NULL; opt++) {
if (strncmp(set_window_option_table[i].name, if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
data->option, strlen(data->option)) != 0)
continue; continue;
if (entry != NULL) { if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->option); ctx->error(ctx, "ambiguous option: %s", data->arg);
return (-1); return (-1);
} }
entry = &set_window_option_table[i]; entry = opt;
/* Bail now if an exact match. */ /* Bail now if an exact match. */
if (strcmp(entry->name, data->option) == 0) if (strcmp(entry->name, data->arg) == 0)
break; break;
} }
if (entry == NULL) { if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->option); ctx->error(ctx, "unknown option: %s", data->arg);
return (-1); return (-1);
} }
if (data->flags & CMD_UFLAG) { if (data->chflags & CMD_CHFLAG('u')) {
if (data->flags & CMD_GFLAG) { if (data->chflags & CMD_CHFLAG('g')) {
ctx->error(ctx, ctx->error(ctx,
"can't unset global option: %s", entry->name); "can't unset global option: %s", entry->name);
return (-1); return (-1);
} }
if (data->value != NULL) { if (data->arg2 != NULL) {
ctx->error(ctx, ctx->error(ctx,
"value passed to unset option: %s", entry->name); "value passed to unset option: %s", entry->name);
return (-1); return (-1);
@@ -131,25 +134,26 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
} else { } else {
switch (entry->type) { switch (entry->type) {
case SET_OPTION_STRING: case SET_OPTION_STRING:
set_option_string(ctx, oo, entry, data->value); set_option_string(ctx, oo, entry,
data->arg2, data->chflags & CMD_CHFLAG('a'));
break; break;
case SET_OPTION_NUMBER: case SET_OPTION_NUMBER:
set_option_number(ctx, oo, entry, data->value); set_option_number(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_KEY: case SET_OPTION_KEY:
set_option_key(ctx, oo, entry, data->value); set_option_key(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_COLOUR: case SET_OPTION_COLOUR:
set_option_colour(ctx, oo, entry, data->value); set_option_colour(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_ATTRIBUTES: case SET_OPTION_ATTRIBUTES:
set_option_attributes(ctx, oo, entry, data->value); set_option_attributes(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_FLAG: case SET_OPTION_FLAG:
set_option_flag(ctx, oo, entry, data->value); set_option_flag(ctx, oo, entry, data->arg2);
break; break;
case SET_OPTION_CHOICE: case SET_OPTION_CHOICE:
set_option_choice(ctx, oo, entry, data->value); set_option_choice(ctx, oo, entry, data->arg2);
break; break;
} }
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-buffer.c,v 1.4 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-show-buffer.c,v 1.10 2009-09-07 23:48:54 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,8 +18,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include "tmux.h" #include "tmux.h"
/* /*
@@ -31,12 +29,10 @@ int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_buffer_entry = { const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb", "show-buffer", "showb",
CMD_BUFFER_SESSION_USAGE, CMD_BUFFER_SESSION_USAGE,
0, 0, 0,
cmd_buffer_init, cmd_buffer_init,
cmd_buffer_parse, cmd_buffer_parse,
cmd_show_buffer_exec, cmd_show_buffer_exec,
cmd_buffer_send,
cmd_buffer_recv,
cmd_buffer_free, cmd_buffer_free,
cmd_buffer_print cmd_buffer_print
}; };
@@ -47,9 +43,9 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
struct cmd_buffer_data *data = self->data; struct cmd_buffer_data *data = self->data;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
u_int size; char *in, *buf, *ptr;
char *buf, *ptr; size_t size, len;
size_t len; u_int width;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
@@ -63,27 +59,43 @@ cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }
if (pb == NULL)
return (0);
if (pb != NULL) { size = pb->size;
size = s->sx; if (size > SIZE_MAX / 4 - 1)
size = SIZE_MAX / 4 - 1;
in = xmalloc(size * 4 + 1);
strvisx(in, pb->data, size, VIS_OCTAL|VIS_TAB);
buf = xmalloc(size + 1); width = s->sx;
len = 0; if (ctx->cmdclient != NULL)
width = ctx->cmdclient->tty.sx;
buf = xmalloc(width + 1);
len = 0;
ptr = in;
do {
buf[len++] = *ptr++;
if (len == width || buf[len - 1] == '\n') {
if (buf[len - 1] == '\n')
len--;
buf[len] = '\0';
ptr = pb->data; ctx->print(ctx, "%s", buf);
do { len = 0;
buf[len++] = *ptr++; }
} while (*ptr != '\0');
if (len == size) {
buf[len] = '\0'; if (len != 0) {
ctx->print(ctx, buf);
len = 0;
}
} while (*ptr != '\0');
buf[len] = '\0'; buf[len] = '\0';
ctx->print(ctx, buf); ctx->print(ctx, "%s", buf);
} }
xfree(buf);
xfree(in);
return (0); return (0);
} }

67
cmd-show-environment.c Normal file
View File

@@ -0,0 +1,67 @@
/* $Id: cmd-show-environment.c,v 1.1 2009-08-09 17:48:55 tcunha Exp $ */
/*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Show environment.
*/
int cmd_show_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv",
"[-g] " CMD_TARGET_SESSION_USAGE,
0, CMD_CHFLAG('g'),
cmd_target_init,
cmd_target_parse,
cmd_show_environment_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
struct environ *env;
struct environ_entry *envent;
if (data->chflags & CMD_CHFLAG('g'))
env = &global_environ;
else {
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
env = &s->environ;
}
RB_FOREACH(envent, environ, env) {
if (envent->value != NULL)
ctx->print(ctx, "%s=%s", envent->name, envent->value);
else
ctx->print(ctx, "-%s", envent->name);
}
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-options.c,v 1.11 2009-01-27 20:22:33 nicm Exp $ */ /* $Id: cmd-show-options.c,v 1.16 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_show_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_options_entry = { const struct cmd_entry cmd_show_options_entry = {
"show-options", "show", "show-options", "show",
"[-g] " CMD_TARGET_SESSION_USAGE, "[-g] " CMD_TARGET_SESSION_USAGE,
CMD_GFLAG, 0, CMD_CHFLAG('g'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_show_options_exec, cmd_show_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,21 +47,18 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s; struct session *s;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry;
u_int i;
char *vs; char *vs;
long long vn; long long vn;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_options; oo = &global_s_options;
else { else {
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
oo = &s->options; oo = &s->options;
} }
for (i = 0; i < NSETOPTION; i++) { for (entry = set_option_table; entry->name != NULL; entry++) {
entry = &set_option_table[i];
if (options_find1(oo, entry->name) == NULL) if (options_find1(oo, entry->name) == NULL)
continue; continue;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-window-options.c,v 1.7 2009-01-27 20:22:33 nicm Exp $ */ /* $Id: cmd-show-window-options.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,12 +32,10 @@ int cmd_show_window_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_window_options_entry = { const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw", "show-window-options", "showw",
"[-g] " CMD_TARGET_WINDOW_USAGE, "[-g] " CMD_TARGET_WINDOW_USAGE,
CMD_GFLAG, 0, CMD_CHFLAG('g'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_show_window_options_exec, cmd_show_window_options_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -49,21 +47,18 @@ cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
struct options *oo; struct options *oo;
const struct set_option_entry *entry; const struct set_option_entry *entry;
u_int i;
char *vs; char *vs;
long long vn; long long vn;
if (data->flags & CMD_GFLAG) if (data->chflags & CMD_CHFLAG('g'))
oo = &global_window_options; oo = &global_w_options;
else { else {
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1); return (-1);
oo = &wl->window->options; oo = &wl->window->options;
} }
for (i = 0; i < NSETWINDOWOPTION; i++) { for (entry = set_window_option_table; entry->name != NULL; entry++) {
entry = &set_window_option_table[i];
if (options_find1(oo, entry->name) == NULL) if (options_find1(oo, entry->name) == NULL)
continue; continue;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-source-file.c,v 1.5 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-source-file.c,v 1.8 2009-08-24 16:27:03 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@@ -26,8 +26,6 @@
int cmd_source_file_parse(struct cmd *, int, char **, char **); int cmd_source_file_parse(struct cmd *, int, char **, char **);
int cmd_source_file_exec(struct cmd *, struct cmd_ctx *); int cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
void cmd_source_file_send(struct cmd *, struct buffer *);
void cmd_source_file_recv(struct cmd *, struct buffer *);
void cmd_source_file_free(struct cmd *); void cmd_source_file_free(struct cmd *);
void cmd_source_file_init(struct cmd *, int); void cmd_source_file_init(struct cmd *, int);
size_t cmd_source_file_print(struct cmd *, char *, size_t); size_t cmd_source_file_print(struct cmd *, char *, size_t);
@@ -39,12 +37,10 @@ struct cmd_source_file_data {
const struct cmd_entry cmd_source_file_entry = { const struct cmd_entry cmd_source_file_entry = {
"source-file", "source", "source-file", "source",
"path", "path",
0, 0, 0,
cmd_source_file_init, cmd_source_file_init,
cmd_source_file_parse, cmd_source_file_parse,
cmd_source_file_exec, cmd_source_file_exec,
cmd_source_file_send,
cmd_source_file_recv,
cmd_source_file_free, cmd_source_file_free,
cmd_source_file_print cmd_source_file_print
}; };
@@ -94,7 +90,7 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
struct cmd_source_file_data *data = self->data; struct cmd_source_file_data *data = self->data;
char *cause; char *cause;
if (load_cfg(data->path, &cause) != 0) { if (load_cfg(data->path, ctx, &cause) != 0) {
ctx->error(ctx, "%s", cause); ctx->error(ctx, "%s", cause);
xfree(cause); xfree(cause);
return (-1); return (-1);
@@ -103,25 +99,6 @@ cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_source_file_send(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->path);
}
void
cmd_source_file_recv(struct cmd *self, struct buffer *b)
{
struct cmd_source_file_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->path = cmd_recv_string(b);
}
void void
cmd_source_file_free(struct cmd *self) cmd_source_file_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-split-window.c,v 1.15 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-split-window.c,v 1.27 2009-09-16 12:36:27 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,8 +29,6 @@
int cmd_split_window_parse(struct cmd *, int, char **, char **); int cmd_split_window_parse(struct cmd *, int, char **, char **);
int cmd_split_window_exec(struct cmd *, struct cmd_ctx *); int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_split_window_send(struct cmd *, struct buffer *);
void cmd_split_window_recv(struct cmd *, struct buffer *);
void cmd_split_window_free(struct cmd *); void cmd_split_window_free(struct cmd *);
void cmd_split_window_init(struct cmd *, int); void cmd_split_window_init(struct cmd *, int);
size_t cmd_split_window_print(struct cmd *, char *, size_t); size_t cmd_split_window_print(struct cmd *, char *, size_t);
@@ -39,25 +37,24 @@ struct cmd_split_window_data {
char *target; char *target;
char *cmd; char *cmd;
int flag_detached; int flag_detached;
int flag_horizontal;
int percentage; int percentage;
int lines; int size;
}; };
const struct cmd_entry cmd_split_window_entry = { const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw", "split-window", "splitw",
"[-d] [-p percentage|-l lines] [-t target-window] [command]", "[-dhv] [-p percentage|-l size] [-t target-window] [command]",
0, 0, 0,
cmd_split_window_init, cmd_split_window_init,
cmd_split_window_parse, cmd_split_window_parse,
cmd_split_window_exec, cmd_split_window_exec,
cmd_split_window_send,
cmd_split_window_recv,
cmd_split_window_free, cmd_split_window_free,
cmd_split_window_print cmd_split_window_print
}; };
void void
cmd_split_window_init(struct cmd *self, unused int arg) cmd_split_window_init(struct cmd *self, int key)
{ {
struct cmd_split_window_data *data; struct cmd_split_window_data *data;
@@ -65,50 +62,63 @@ cmd_split_window_init(struct cmd *self, unused int arg)
data->target = NULL; data->target = NULL;
data->cmd = NULL; data->cmd = NULL;
data->flag_detached = 0; data->flag_detached = 0;
data->flag_horizontal = 0;
data->percentage = -1; data->percentage = -1;
data->lines = -1; data->size = -1;
switch (key) {
case '%':
data->flag_horizontal = 1;
break;
case '"':
data->flag_horizontal = 0;
break;
}
} }
int int
cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_split_window_data *data; struct cmd_split_window_data *data;
int opt, n; int opt;
const char *errstr; const char *errstr;
self->entry->init(self, 0); self->entry->init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, "dl:p:t:")) != -1) { while ((opt = getopt(argc, argv, "dhl:p:t:v")) != -1) {
switch (opt) { switch (opt) {
case 'd': case 'd':
data->flag_detached = 1; data->flag_detached = 1;
break; break;
case 'h':
data->flag_horizontal = 1;
break;
case 't': case 't':
if (data->target == NULL) if (data->target == NULL)
data->target = xstrdup(optarg); data->target = xstrdup(optarg);
break; break;
case 'l': case 'l':
if (data->percentage == -1 && data->lines == -1) { if (data->percentage != -1 || data->size != -1)
n = strtonum(optarg, 1, INT_MAX, &errstr); break;
if (errstr != NULL) { data->size = strtonum(optarg, 1, INT_MAX, &errstr);
xasprintf(cause, "lines %s", errstr); if (errstr != NULL) {
goto error; xasprintf(cause, "size %s", errstr);
} goto error;
data->lines = n;
} }
break; break;
case 'p': case 'p':
if (data->lines == -1 && data->percentage == -1) { if (data->size != -1 || data->percentage != -1)
n = strtonum(optarg, 1, 100, &errstr); break;
if (errstr != NULL) { data->percentage = strtonum(optarg, 1, 100, &errstr);
xasprintf( if (errstr != NULL) {
cause, "percentage %s", errstr); xasprintf(cause, "percentage %s", errstr);
goto error; goto error;
}
data->percentage = n;
} }
break; break;
case 'v':
data->flag_horizontal = 0;
break;
default: default:
goto usage; goto usage;
} }
@@ -139,38 +149,53 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
const char **env; struct environ env;
char *cmd, *cwd, *cause; char *cmd, *cwd, *cause;
const char *shell;
u_int hlimit; u_int hlimit;
int lines; int size;
enum layout_type type;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
env = server_fill_environ(s); environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
cmd = data->cmd; cmd = data->cmd;
if (cmd == NULL) if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL) if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&global_options, "default-path"); cwd = options_get_string(&s->options, "default-path");
else else
cwd = ctx->cmdclient->cwd; cwd = ctx->cmdclient->cwd;
lines = -1; size = -1;
if (data->lines != -1) if (data->size != -1)
lines = data->lines; size = data->size;
else if (data->percentage != -1) else if (data->percentage != -1)
lines = (w->active->sy * data->percentage) / 100; size = (w->active->sy * data->percentage) / 100;
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(&s->options, "history-limit");
wp = window_add_pane(w, lines, cmd, cwd, env, hlimit, &cause);
if (wp == NULL) { type = LAYOUT_TOPBOTTOM;
ctx->error(ctx, "create pane failed: %s", cause); if (data->flag_horizontal)
xfree(cause); type = LAYOUT_LEFTRIGHT;
return (-1);
shell = options_get_string(&s->options, "default-shell");
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
wp = window_add_pane(w, hlimit);
if (window_pane_spawn(wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
goto error;
if (layout_split_pane(w->active, type, size, wp) != 0) {
cause = xstrdup("pane too small");
goto error;
} }
server_redraw_window(w); server_redraw_window(w);
if (!data->flag_detached) { if (!data->flag_detached) {
@@ -179,30 +204,17 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_session(s); server_redraw_session(s);
} else } else
server_status_session(s); server_status_session(s);
layout_refresh(w, 0);
environ_free(&env);
return (0); return (0);
}
void error:
cmd_split_window_send(struct cmd *self, struct buffer *b) environ_free(&env);
{ if (wp != NULL)
struct cmd_split_window_data *data = self->data; window_remove_pane(w, wp);
ctx->error(ctx, "create pane failed: %s", cause);
buffer_write(b, data, sizeof *data); xfree(cause);
cmd_send_string(b, data->target); return (-1);
cmd_send_string(b, data->cmd);
}
void
cmd_split_window_recv(struct cmd *self, struct buffer *b)
{
struct cmd_split_window_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
data->cmd = cmd_recv_string(b);
} }
void void
@@ -228,6 +240,14 @@ cmd_split_window_print(struct cmd *self, char *buf, size_t len)
return (off); return (off);
if (off < len && data->flag_detached) if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d"); off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->flag_horizontal)
off += xsnprintf(buf + off, len - off, " -h");
if (off < len && data->size > 0)
off += xsnprintf(buf + off, len - off, " -l %d", data->size);
if (off < len && data->percentage > 0) {
off += xsnprintf(
buf + off, len - off, " -p %d", data->percentage);
}
if (off < len && data->target != NULL) if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target); off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->cmd != NULL) if (off < len && data->cmd != NULL)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-start-server.c,v 1.6 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-start-server.c,v 1.8 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,13 +29,11 @@ int cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_start_server_entry = { const struct cmd_entry cmd_start_server_entry = {
"start-server", "start", "start-server", "start",
"", "",
CMD_STARTSERVER, CMD_STARTSERVER, 0,
NULL, NULL,
NULL, NULL,
cmd_start_server_exec, cmd_start_server_exec,
NULL, NULL,
NULL,
NULL,
NULL NULL
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-string.c,v 1.17 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd-string.c,v 1.23 2009-08-09 17:48:55 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,9 +19,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -33,6 +35,7 @@ int cmd_string_getc(const char *, size_t *);
void cmd_string_ungetc(const char *, size_t *); void cmd_string_ungetc(const char *, size_t *);
char *cmd_string_string(const char *, size_t *, char, int); char *cmd_string_string(const char *, size_t *, char, int);
char *cmd_string_variable(const char *, size_t *); char *cmd_string_variable(const char *, size_t *);
char *cmd_string_expand_tilde(const char *, size_t *);
int int
cmd_string_getc(const char *s, size_t *p) cmd_string_getc(const char *s, size_t *p)
@@ -56,21 +59,11 @@ int
cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause) cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
{ {
size_t p; size_t p;
int ch, argc, rval, have_arg; int ch, i, argc, rval, have_arg;
char **argv, *buf, *t, *u; char **argv, *buf, *t;
const char *whitespace, *equals;
size_t len; size_t len;
if ((t = strchr(s, ' ')) == NULL && (t = strchr(s, '\t')) == NULL)
t = strchr(s, '\0');
if ((u = strchr(s, '=')) != NULL && u < t) {
if (putenv(xstrdup(s)) != 0) {
xasprintf(cause, "assignment failed: %s", s);
return (-1);
}
*cmdlist = NULL;
return (0);
}
argv = NULL; argv = NULL;
argc = 0; argc = 0;
@@ -114,6 +107,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
buf = xrealloc(buf, 1, len + strlen(t) + 1); buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1); strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t); len += strlen(t);
xfree(t);
have_arg = 1; have_arg = 1;
break; break;
@@ -143,6 +137,18 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
if (argc == 0) if (argc == 0)
goto out; goto out;
for (i = 0; i < argc; i++) {
equals = strchr(argv[i], '=');
whitespace = argv[i] + strcspn(argv[i], " \t");
if (equals == NULL || equals > whitespace)
break;
environ_put(&global_environ, argv[i]);
memmove(&argv[i], &argv[i + 1], argc - i - 1);
argc--;
}
if (argc == 0)
goto out;
*cmdlist = cmd_list_parse(argc, argv, cause); *cmdlist = cmd_list_parse(argc, argv, cause);
if (*cmdlist == NULL) if (*cmdlist == NULL)
goto out; goto out;
@@ -153,6 +159,17 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
rval = 0; rval = 0;
goto out; goto out;
case '~':
if (have_arg == 0) {
if ((t = cmd_string_expand_tilde(s, &p)) == NULL)
goto error;
buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t);
xfree(t);
break;
}
/* FALLTHROUGH */
default: default:
if (len >= SIZE_MAX - 2) if (len >= SIZE_MAX - 2)
goto error; goto error;
@@ -200,6 +217,9 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
switch (ch = cmd_string_getc(s, p)) { switch (ch = cmd_string_getc(s, p)) {
case EOF: case EOF:
goto error; goto error;
case 'e':
ch = '\033';
break;
case 'r': case 'r':
ch = '\r'; ch = '\r';
break; break;
@@ -219,6 +239,7 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
buf = xrealloc(buf, 1, len + strlen(t) + 1); buf = xrealloc(buf, 1, len + strlen(t) + 1);
strlcpy(buf + len, t, strlen(t) + 1); strlcpy(buf + len, t, strlen(t) + 1);
len += strlen(t); len += strlen(t);
xfree(t);
continue; continue;
} }
@@ -307,3 +328,31 @@ error:
xfree(buf); xfree(buf);
return (NULL); return (NULL);
} }
char *
cmd_string_expand_tilde(const char *s, size_t *p)
{
struct passwd *pw;
char *home, *path, *username;
home = NULL;
if (cmd_string_getc(s, p) == '/') {
if ((home = getenv("HOME")) == NULL) {
if ((pw = getpwuid(getuid())) != NULL)
home = pw->pw_dir;
}
} else {
cmd_string_ungetc(s, p);
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
return (NULL);
if ((pw = getpwnam(username)) != NULL)
home = pw->pw_dir;
if (username != NULL)
xfree(username);
}
if (home == NULL)
return (NULL);
xasprintf(&path, "%s/", home);
return (path);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-suspend-client.c,v 1.2 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-suspend-client.c,v 1.4 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -37,12 +37,10 @@ struct cmd_suspend_client_data {
const struct cmd_entry cmd_suspend_client_entry = { const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc", "suspend-client", "suspendc",
"[-c target-client]", "[-c target-client]",
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_suspend_client_exec, cmd_suspend_client_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-swap-pane.c,v 1.6 2009-06-25 15:28:08 nicm Exp $ */ /* $Id: cmd-swap-pane.c,v 1.13 2009-07-30 21:04:40 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,269 +26,118 @@
* Swap two panes. * Swap two panes.
*/ */
int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_swap_pane_send(struct cmd *, struct buffer *);
void cmd_swap_pane_recv(struct cmd *, struct buffer *);
void cmd_swap_pane_free(struct cmd *);
void cmd_swap_pane_init(struct cmd *, int); void cmd_swap_pane_init(struct cmd *, int);
size_t cmd_swap_pane_print(struct cmd *, char *, size_t); int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
struct cmd_swap_pane_data {
char *target;
int src;
int dst;
int flag_detached;
int flag_up;
int flag_down;
};
const struct cmd_entry cmd_swap_pane_entry = { const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp", "swap-pane", "swapp",
"[-dDU] [-t target-window] [-p src-index] [-q dst-index]", "[-dDU] " CMD_SRCDST_PANE_USAGE,
0, 0, CMD_CHFLAG('d')|CMD_CHFLAG('D')|CMD_CHFLAG('U'),
cmd_swap_pane_init, cmd_swap_pane_init,
cmd_swap_pane_parse, cmd_srcdst_parse,
cmd_swap_pane_exec, cmd_swap_pane_exec,
cmd_swap_pane_send, cmd_srcdst_free,
cmd_swap_pane_recv, cmd_srcdst_print
cmd_swap_pane_free,
cmd_swap_pane_print
}; };
void void
cmd_swap_pane_init(struct cmd *self, int key) cmd_swap_pane_init(struct cmd *self, int key)
{ {
struct cmd_swap_pane_data *data; struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data); cmd_srcdst_init(self, key);
data->target = NULL;
data->src = -1;
data->dst = -1;
data->flag_detached = 0;
data->flag_up = 0;
data->flag_down = 0;
switch (key) {
case '{':
data->flag_up = 1;
break;
case '}':
data->flag_down = 1;
break;
}
}
int
cmd_swap_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_swap_pane_data *data;
int opt, n;
const char *errstr;
self->entry->init(self, 0);
data = self->data; data = self->data;
while ((opt = getopt(argc, argv, "dDt:p:q:U")) != -1) { if (key == '{')
switch (opt) { data->chflags |= CMD_CHFLAG('U');
case 'd': else if (key == '}')
data->flag_detached = 1; data->chflags |= CMD_CHFLAG('D');
break;
case 'D':
data->flag_up = 0;
data->flag_down = 1;
data->dst = -1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'p':
if (data->src == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "src %s", errstr);
goto error;
}
data->src = n;
}
break;
case 'q':
if (data->dst == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "dst %s", errstr);
goto error;
}
data->dst = n;
}
data->flag_up = 0;
data->flag_down = 0;
break;
case 'U':
data->flag_up = 1;
data->flag_down = 0;
data->dst = -1;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
} }
int int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_swap_pane_data *data = self->data; struct cmd_srcdst_data *data = self->data;
struct winlink *wl; struct winlink *src_wl, *dst_wl;
struct window *w; struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp; struct window_pane *tmp_wp, *src_wp, *dst_wp;
u_int xx, yy; struct layout_cell *src_lc, *dst_lc;
int flags; u_int sx, sy, xoff, yoff;
if (data == NULL) if (data == NULL)
return (0); return (0);
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((dst_wl = cmd_find_pane(ctx, data->dst, NULL, &dst_wp)) == NULL)
return (-1); return (-1);
w = wl->window; dst_w = dst_wl->window;
if (data->src == -1) if (data->src == NULL) {
src_wp = w->active; src_w = dst_w;
else { if (data->chflags & CMD_CHFLAG('D')) {
src_wp = window_pane_at_index(w, data->src); src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL) { if (src_wp == NULL)
ctx->error(ctx, "no pane: %d", data->src); src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (data->chflags & CMD_CHFLAG('U')) {
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else
return (0);
} else {
src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp);
if (src_wl == NULL)
return (-1); return (-1);
} src_w = src_wl->window;
}
if (data->dst == -1)
dst_wp = w->active;
else {
dst_wp = window_pane_at_index(w, data->dst);
if (dst_wp == NULL) {
ctx->error(ctx, "no pane: %d", data->dst);
return (-1);
}
}
if (data->dst == -1 && data->flag_up) {
if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
dst_wp = TAILQ_LAST(&w->panes, window_panes);
}
if (data->dst == -1 && data->flag_down) {
if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
dst_wp = TAILQ_FIRST(&w->panes);
} }
if (src_wp == dst_wp) if (src_wp == dst_wp)
return (0); return (0);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry); tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
TAILQ_REMOVE(&w->panes, dst_wp, entry); TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry); TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
if (tmp_wp == src_wp) if (tmp_wp == src_wp)
tmp_wp = dst_wp; tmp_wp = dst_wp;
if (tmp_wp == NULL) if (tmp_wp == NULL)
TAILQ_INSERT_HEAD(&w->panes, src_wp, entry); TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry);
else else
TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry); TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);
xx = src_wp->xoff; src_lc = src_wp->layout_cell;
yy = src_wp->yoff; dst_lc = dst_wp->layout_cell;
flags = src_wp->flags; src_lc->wp = dst_wp;
src_wp->xoff = dst_wp->xoff; dst_wp->layout_cell = src_lc;
src_wp->yoff = dst_wp->yoff; dst_lc->wp = src_wp;
src_wp->flags &= ~PANE_HIDDEN; src_wp->layout_cell = dst_lc;
src_wp->flags |= dst_wp->flags & PANE_HIDDEN;
dst_wp->xoff = xx; src_wp->window = dst_w;
dst_wp->yoff = yy; dst_wp->window = src_w;
dst_wp->flags &= ~PANE_HIDDEN;
dst_wp->flags |= flags & PANE_HIDDEN;
xx = src_wp->sx; sx = src_wp->sx; sy = src_wp->sy;
yy = src_wp->sy; xoff = src_wp->xoff; yoff = src_wp->yoff;
src_wp->xoff = dst_wp->xoff; src_wp->yoff = dst_wp->yoff;
window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy); window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
window_pane_resize(dst_wp, xx, yy); dst_wp->xoff = xoff; dst_wp->yoff = yoff;
window_pane_resize(dst_wp, sx, sy);
if (!data->flag_detached) { if (!(data->chflags & CMD_CHFLAG('d'))) {
tmp_wp = dst_wp; if (src_w != dst_w) {
if (tmp_wp->flags & PANE_HIDDEN) window_set_active_pane(src_w, dst_wp);
tmp_wp = src_wp; window_set_active_pane(dst_w, src_wp);
window_set_active_pane(w, tmp_wp); } else {
layout_refresh(w, 0); tmp_wp = dst_wp;
if (!window_pane_visible(tmp_wp))
tmp_wp = src_wp;
window_set_active_pane(src_w, tmp_wp);
}
} else {
if (src_w->active == src_wp)
window_set_active_pane(src_w, dst_wp);
if (dst_w->active == dst_wp)
window_set_active_pane(dst_w, src_wp);
} }
server_redraw_window(src_w);
server_redraw_window(dst_w);
return (0); return (0);
} }
void
cmd_swap_pane_send(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->target);
}
void
cmd_swap_pane_recv(struct cmd *self, struct buffer *b)
{
struct cmd_swap_pane_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->target = cmd_recv_string(b);
}
void
cmd_swap_pane_free(struct cmd *self)
{
struct cmd_swap_pane_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_swap_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len &&
(data->flag_down || data->flag_up || data->flag_detached)) {
off += xsnprintf(buf + off, len - off, " -");
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, "d");
if (off < len && data->flag_up)
off += xsnprintf(buf + off, len - off, "D");
if (off < len && data->flag_down)
off += xsnprintf(buf + off, len - off, "U");
}
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->src != -1)
off += xsnprintf(buf + off, len - off, " -p %d", data->src);
if (off < len && data->dst != -1)
off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-swap-window.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-swap-window.c,v 1.17 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,12 +31,10 @@ int cmd_swap_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_window_entry = { const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw", "swap-window", "swapw",
"[-d] " CMD_SRCDST_WINDOW_USAGE, "[-d] " CMD_SRCDST_WINDOW_USAGE,
CMD_DFLAG, 0, CMD_CHFLAG('d'),
cmd_srcdst_init, cmd_srcdst_init,
cmd_srcdst_parse, cmd_srcdst_parse,
cmd_swap_window_exec, cmd_swap_window_exec,
cmd_srcdst_send,
cmd_srcdst_recv,
cmd_srcdst_free, cmd_srcdst_free,
cmd_srcdst_print cmd_srcdst_print
}; };
@@ -61,7 +59,7 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
wl_dst->window = wl_src->window; wl_dst->window = wl_src->window;
wl_src->window = w; wl_src->window = w;
if (!(data->flags & CMD_DFLAG)) { if (!(data->chflags & CMD_CHFLAG('d'))) {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);
if (src != dst) if (src != dst)
session_select(src, wl_src->idx); session_select(src, wl_src->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-switch-client.c,v 1.15 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-switch-client.c,v 1.17 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,8 +29,6 @@
int cmd_switch_client_parse(struct cmd *, int, char **, char **); int cmd_switch_client_parse(struct cmd *, int, char **, char **);
int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *); int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_switch_client_send(struct cmd *, struct buffer *);
void cmd_switch_client_recv(struct cmd *, struct buffer *);
void cmd_switch_client_free(struct cmd *); void cmd_switch_client_free(struct cmd *);
size_t cmd_switch_client_print(struct cmd *, char *, size_t); size_t cmd_switch_client_print(struct cmd *, char *, size_t);
@@ -42,12 +40,10 @@ struct cmd_switch_client_data {
const struct cmd_entry cmd_switch_client_entry = { const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc", "switch-client", "switchc",
"[-c target-client] [-t target-session]", "[-c target-client] [-t target-session]",
0, 0, 0,
NULL, NULL,
cmd_switch_client_parse, cmd_switch_client_parse,
cmd_switch_client_exec, cmd_switch_client_exec,
cmd_switch_client_send,
cmd_switch_client_recv,
cmd_switch_client_free, cmd_switch_client_free,
cmd_switch_client_print cmd_switch_client_print
}; };
@@ -111,27 +107,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
void
cmd_switch_client_send(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data = self->data;
buffer_write(b, data, sizeof *data);
cmd_send_string(b, data->name);
cmd_send_string(b, data->target);
}
void
cmd_switch_client_recv(struct cmd *self, struct buffer *b)
{
struct cmd_switch_client_data *data;
self->data = data = xmalloc(sizeof *data);
buffer_read(b, data, sizeof *data);
data->name = cmd_recv_string(b);
data->target = cmd_recv_string(b);
}
void void
cmd_switch_client_free(struct cmd *self) cmd_switch_client_free(struct cmd *self)
{ {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-unbind-key.c,v 1.16 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-unbind-key.c,v 1.20 2009-07-28 23:19:06 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,23 +26,24 @@
int cmd_unbind_key_parse(struct cmd *, int, char **, char **); int cmd_unbind_key_parse(struct cmd *, int, char **, char **);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *); int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_unbind_key_send(struct cmd *, struct buffer *);
void cmd_unbind_key_recv(struct cmd *, struct buffer *);
void cmd_unbind_key_free(struct cmd *); void cmd_unbind_key_free(struct cmd *);
int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *);
struct cmd_unbind_key_data { struct cmd_unbind_key_data {
int key; int key;
int command_key;
char *tablename;
}; };
const struct cmd_entry cmd_unbind_key_entry = { const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind", "unbind-key", "unbind",
"key", "[-cn] [-t key-table] key",
0, 0, 0,
NULL, NULL,
cmd_unbind_key_parse, cmd_unbind_key_parse,
cmd_unbind_key_exec, cmd_unbind_key_exec,
cmd_unbind_key_send,
cmd_unbind_key_recv,
cmd_unbind_key_free, cmd_unbind_key_free,
NULL NULL
}; };
@@ -51,12 +52,23 @@ int
cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
{ {
struct cmd_unbind_key_data *data; struct cmd_unbind_key_data *data;
int opt; int opt, no_prefix = 0;
self->data = data = xmalloc(sizeof *data); self->data = data = xmalloc(sizeof *data);
data->command_key = 0;
data->tablename = NULL;
while ((opt = getopt(argc, argv, "")) != -1) { while ((opt = getopt(argc, argv, "cnt:")) != -1) {
switch (opt) { switch (opt) {
case 'c':
data->command_key = 1;
break;
case 'n':
no_prefix = 1;
break;
case 't':
data->tablename = xstrdup(optarg);
break;
default: default:
goto usage; goto usage;
} }
@@ -70,6 +82,8 @@ cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
xasprintf(cause, "unknown key: %s", argv[0]); xasprintf(cause, "unknown key: %s", argv[0]);
goto error; goto error;
} }
if (!no_prefix)
data->key |= KEYC_PREFIX;
return (0); return (0);
@@ -88,27 +102,33 @@ cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
if (data == NULL) if (data == NULL)
return (0); return (0);
if (data->tablename != NULL)
return (cmd_unbind_key_table(self, ctx));
key_bindings_remove(data->key); key_bindings_remove(data->key);
return (0); return (0);
} }
void int
cmd_unbind_key_send(struct cmd *self, struct buffer *b) cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_unbind_key_data *data = self->data; struct cmd_unbind_key_data *data = self->data;
const struct mode_key_table *mtab;
struct mode_key_binding *mbind, mtmp;
buffer_write(b, data, sizeof *data); if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
} ctx->error(ctx, "unknown key table: %s", data->tablename);
return (-1);
}
void mtmp.key = data->key & ~KEYC_PREFIX;
cmd_unbind_key_recv(struct cmd *self, struct buffer *b) mtmp.mode = data->command_key ? 1 : 0;
{ if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
struct cmd_unbind_key_data *data; SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
xfree(mbind);
self->data = data = xmalloc(sizeof *data); }
buffer_read(b, data, sizeof *data); return (0);
} }
void void
@@ -116,5 +136,7 @@ cmd_unbind_key_free(struct cmd *self)
{ {
struct cmd_unbind_key_data *data = self->data; struct cmd_unbind_key_data *data = self->data;
if (data->tablename != NULL)
xfree(data->tablename);
xfree(data); xfree(data);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-unlink-window.c,v 1.13 2009-01-19 18:23:40 nicm Exp $ */ /* $Id: cmd-unlink-window.c,v 1.16 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,11 @@ int cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_unlink_window_entry = { const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw", "unlink-window", "unlinkw",
CMD_TARGET_WINDOW_USAGE, "[-k] " CMD_TARGET_WINDOW_USAGE,
0, 0, CMD_CHFLAG('k'),
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_unlink_window_exec, cmd_unlink_window_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -52,7 +50,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
return (-1); return (-1);
if (wl->window->references == 1) { if (!(data->chflags & CMD_CHFLAG('k')) && wl->window->references == 1) {
ctx->error(ctx, "window is only linked to one session"); ctx->error(ctx, "window is only linked to one session");
return (-1); return (-1);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-up-pane.c,v 1.7 2009-04-01 21:10:08 nicm Exp $ */ /* $Id: cmd-up-pane.c,v 1.12 2009-07-28 22:12:16 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,12 +29,10 @@ int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_up_pane_entry = { const struct cmd_entry cmd_up_pane_entry = {
"up-pane", "upp", "up-pane", "upp",
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, 0, 0,
cmd_target_init, cmd_target_init,
cmd_target_parse, cmd_target_parse,
cmd_up_pane_exec, cmd_up_pane_exec,
cmd_target_send,
cmd_target_recv,
cmd_target_free, cmd_target_free,
cmd_target_print cmd_target_print
}; };
@@ -54,8 +52,8 @@ cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
w->active = TAILQ_PREV(w->active, window_panes, entry); w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL) if (w->active == NULL)
w->active = TAILQ_LAST(&w->panes, window_panes); w->active = TAILQ_LAST(&w->panes, window_panes);
layout_refresh(w, 1); } while (!window_pane_visible(w->active));
} while (w->active->flags & PANE_HIDDEN); server_status_window(wl->window);
return (0); return (0);
} }

779
cmd.c
View File

@@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.97 2009-06-25 16:21:32 nicm Exp $ */ /* $Id: cmd.c,v 1.115 2009-08-31 22:30:15 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <fnmatch.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@@ -29,6 +30,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_attach_session_entry, &cmd_attach_session_entry,
&cmd_bind_key_entry, &cmd_bind_key_entry,
&cmd_break_pane_entry, &cmd_break_pane_entry,
&cmd_choose_client_entry,
&cmd_choose_session_entry, &cmd_choose_session_entry,
&cmd_choose_window_entry, &cmd_choose_window_entry,
&cmd_clear_history_entry, &cmd_clear_history_entry,
@@ -39,9 +41,12 @@ const struct cmd_entry *cmd_table[] = {
&cmd_copy_mode_entry, &cmd_copy_mode_entry,
&cmd_delete_buffer_entry, &cmd_delete_buffer_entry,
&cmd_detach_client_entry, &cmd_detach_client_entry,
&cmd_display_message_entry,
&cmd_display_panes_entry,
&cmd_down_pane_entry, &cmd_down_pane_entry,
&cmd_find_window_entry, &cmd_find_window_entry,
&cmd_has_session_entry, &cmd_has_session_entry,
&cmd_if_shell_entry,
&cmd_kill_pane_entry, &cmd_kill_pane_entry,
&cmd_kill_server_entry, &cmd_kill_server_entry,
&cmd_kill_session_entry, &cmd_kill_session_entry,
@@ -80,10 +85,12 @@ const struct cmd_entry *cmd_table[] = {
&cmd_send_prefix_entry, &cmd_send_prefix_entry,
&cmd_server_info_entry, &cmd_server_info_entry,
&cmd_set_buffer_entry, &cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_option_entry, &cmd_set_option_entry,
&cmd_set_password_entry, &cmd_set_password_entry,
&cmd_set_window_option_entry, &cmd_set_window_option_entry,
&cmd_show_buffer_entry, &cmd_show_buffer_entry,
&cmd_show_environment_entry,
&cmd_show_options_entry, &cmd_show_options_entry,
&cmd_show_window_options_entry, &cmd_show_window_options_entry,
&cmd_source_file_entry, &cmd_source_file_entry,
@@ -99,13 +106,77 @@ const struct cmd_entry *cmd_table[] = {
NULL NULL
}; };
struct session *cmd_newest_session(struct sessions *);
struct client *cmd_lookup_client(const char *);
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 *);
int
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
{
size_t arglen;
int i;
*buf = '\0';
for (i = 0; i < argc; i++) {
if (strlcpy(buf, argv[i], len) >= len)
return (-1);
arglen = strlen(argv[i]) + 1;
buf += arglen;
len -= arglen;
}
return (0);
}
int
cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
{
int i;
size_t arglen;
if (argc == 0)
return (0);
*argv = xcalloc(argc, sizeof **argv);
buf[len - 1] = '\0';
for (i = 0; i < argc; i++) {
if (len == 0) {
cmd_free_argv(argc, *argv);
return (-1);
}
arglen = strlen(buf) + 1;
(*argv)[i] = xstrdup(buf);
buf += arglen;
len -= arglen;
}
return (0);
}
void
cmd_free_argv(int argc, char **argv)
{
int i;
if (argc == 0)
return;
for (i = 0; i < argc; i++) {
if (argv[i] != NULL)
xfree(argv[i]);
}
xfree(argv);
}
struct cmd * struct cmd *
cmd_parse(int argc, char **argv, char **cause) cmd_parse(int argc, char **argv, char **cause)
{ {
const struct cmd_entry **entryp, *entry; const struct cmd_entry **entryp, *entry;
struct cmd *cmd; struct cmd *cmd;
char s[BUFSIZ]; char s[BUFSIZ];
int opt; int opt, ambiguous = 0;
*cause = NULL; *cause = NULL;
if (argc == 0) { if (argc == 0) {
@@ -117,6 +188,7 @@ cmd_parse(int argc, char **argv, char **cause)
for (entryp = cmd_table; *entryp != NULL; entryp++) { for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL && if ((*entryp)->alias != NULL &&
strcmp((*entryp)->alias, argv[0]) == 0) { strcmp((*entryp)->alias, argv[0]) == 0) {
ambiguous = 0;
entry = *entryp; entry = *entryp;
break; break;
} }
@@ -124,13 +196,15 @@ cmd_parse(int argc, char **argv, char **cause)
if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0) if (strncmp((*entryp)->name, argv[0], strlen(argv[0])) != 0)
continue; continue;
if (entry != NULL) if (entry != NULL)
goto ambiguous; ambiguous = 1;
entry = *entryp; entry = *entryp;
/* Bail now if an exact match. */ /* Bail now if an exact match. */
if (strcmp(entry->name, argv[0]) == 0) if (strcmp(entry->name, argv[0]) == 0)
break; break;
} }
if (ambiguous)
goto ambiguous;
if (entry == NULL) { if (entry == NULL) {
xasprintf(cause, "unknown command: %s", argv[0]); xasprintf(cause, "unknown command: %s", argv[0]);
return (NULL); return (NULL);
@@ -191,53 +265,6 @@ cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
return (cmd->entry->exec(cmd, ctx)); return (cmd->entry->exec(cmd, ctx));
} }
void
cmd_send(struct cmd *cmd, struct buffer *b)
{
const struct cmd_entry **entryp;
u_int n;
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (*entryp == cmd->entry)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
buffer_write(b, &n, sizeof n);
if (cmd->entry->send != NULL)
cmd->entry->send(cmd, b);
}
struct cmd *
cmd_recv(struct buffer *b)
{
const struct cmd_entry **entryp;
struct cmd *cmd;
u_int m, n;
buffer_read(b, &m, sizeof m);
n = 0;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if (n == m)
break;
n++;
}
if (*entryp == NULL)
fatalx("command not found");
cmd = xmalloc(sizeof *cmd);
cmd->entry = *entryp;
if (cmd->entry->recv != NULL)
cmd->entry->recv(cmd, b);
return (cmd);
}
void void
cmd_free(struct cmd *cmd) cmd_free(struct cmd *cmd)
{ {
@@ -255,141 +282,621 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
return (cmd->entry->print(cmd, buf, len)); return (cmd->entry->print(cmd, buf, len));
} }
void /*
cmd_send_string(struct buffer *b, const char *s) * Figure out the current session. Use: 1) the current session, if the command
{ * context has one; 2) the session containing the pty of the calling client, if
size_t n; * any 3) the session specified in the TMUX variable from the environment (as
* passed from the client); 3) the newest session.
if (s == NULL) { */
n = 0;
buffer_write(b, &n, sizeof n);
return;
}
n = strlen(s) + 1;
buffer_write(b, &n, sizeof n);
buffer_write(b, s, n);
}
char *
cmd_recv_string(struct buffer *b)
{
char *s;
size_t n;
buffer_read(b, &n, sizeof n);
if (n == 0)
return (NULL);
s = xmalloc(n);
buffer_read(b, s, n);
s[n - 1] = '\0';
return (s);
}
struct session * struct session *
cmd_current_session(struct cmd_ctx *ctx) cmd_current_session(struct cmd_ctx *ctx)
{ {
struct msg_command_data *data = ctx->msgdata; struct msg_command_data *data = ctx->msgdata;
struct timeval *tv; struct client *c = ctx->cmdclient;
struct session *s, *newest = NULL; struct session *s;
struct sessions ss;
struct winlink *wl;
struct window_pane *wp;
u_int i; u_int i;
int found;
if (ctx->cursession != NULL) if (ctx->curclient != NULL && ctx->curclient->session != NULL)
return (ctx->cursession); return (ctx->curclient->session);
/*
* If the name of the calling client's pty is know, build a list of the
* sessions that contain it and if any choose either the first or the
* newest.
*/
if (c != NULL && c->tty.path != NULL) {
ARRAY_INIT(&ss);
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
continue;
found = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
if (strcmp(wp->tty, c->tty.path) == 0) {
found = 1;
break;
}
}
if (found)
break;
}
if (found)
ARRAY_ADD(&ss, s);
}
s = cmd_newest_session(&ss);
ARRAY_FREE(&ss);
if (s != NULL)
return (s);
}
/* Use the session from the TMUX environment variable. */
if (data != NULL && data->pid != -1) { if (data != NULL && data->pid != -1) {
if (data->pid != getpid()) { if (data->pid != getpid())
ctx->error(ctx, "wrong server: %ld", (long) data->pid);
return (NULL); return (NULL);
} if (data->idx > ARRAY_LENGTH(&sessions))
if (data->idx > ARRAY_LENGTH(&sessions)) {
ctx->error(ctx, "index out of range: %d", data->idx);
return (NULL); return (NULL);
} if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL)
if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) {
ctx->error(ctx, "session doesn't exist: %u", data->idx);
return (NULL); return (NULL);
}
return (s); return (s);
} }
tv = NULL; return (cmd_newest_session(&sessions));
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { }
s = ARRAY_ITEM(&sessions, i);
if (s != NULL && (tv == NULL || timercmp(&s->tv, tv, >))) { /* Find the newest session. */
newest = ARRAY_ITEM(&sessions, i); struct session *
cmd_newest_session(struct sessions *ss)
{
struct session *s, *snewest;
struct timeval *tv = NULL;
u_int i;
snewest = NULL;
for (i = 0; i < ARRAY_LENGTH(ss); i++) {
if ((s = ARRAY_ITEM(ss, i)) == NULL)
continue;
if (tv == NULL || timercmp(&s->tv, tv, >)) {
snewest = s;
tv = &s->tv; tv = &s->tv;
} }
} }
return (newest);
return (snewest);
} }
/* Find the target client or report an error and return NULL. */
struct client * struct client *
cmd_find_client(struct cmd_ctx *ctx, const char *arg) cmd_find_client(struct cmd_ctx *ctx, const char *arg)
{ {
struct client *c; struct client *c;
char *tmparg;
size_t arglen;
/* A NULL argument means the current client. */
if (arg == NULL) if (arg == NULL)
c = ctx->curclient; return (ctx->curclient);
else { tmparg = xstrdup(arg);
if ((c = arg_parse_client(arg)) == NULL) {
if (arg != NULL) /* Trim a single trailing colon if any. */
ctx->error(ctx, "client not found: %s", arg); arglen = strlen(tmparg);
else if (arglen != 0 && tmparg[arglen - 1] == ':')
ctx->error(ctx, "no client found"); tmparg[arglen - 1] = '\0';
}
} /* Find the client, if any. */
c = cmd_lookup_client(tmparg);
/* If no client found, report an error. */
if (c == NULL)
ctx->error(ctx, "client not found: %s", tmparg);
xfree(tmparg);
return (c); return (c);
} }
/*
* Lookup a client by device path. Either of a full match and a match without a
* leading _PATH_DEV ("/dev/") is accepted.
*/
struct client *
cmd_lookup_client(const char *name)
{
struct client *c;
const char *path;
u_int i;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
if ((c = ARRAY_ITEM(&clients, i)) == NULL)
continue;
path = c->tty.path;
/* Check for exact matches. */
if (strcmp(name, path) == 0)
return (c);
/* Check without leading /dev if present. */
if (strncmp(path, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0)
continue;
if (strcmp(name, path + (sizeof _PATH_DEV) - 1) == 0)
return (c);
}
return (NULL);
}
/* Lookup a session by name. If no session is found, NULL is returned. */
struct session *
cmd_lookup_session(const char *name, int *ambiguous)
{
struct session *s, *sfound;
u_int i;
*ambiguous = 0;
/*
* Look for matches. Session names must be unique so an exact match
* can't be ambigious and can just be returned.
*/
sfound = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
continue;
/* Check for an exact match and return it if found. */
if (strcmp(name, s->name) == 0)
return (s);
/* Then check for pattern matches. */
if (strncmp(name, s->name, strlen(name)) == 0 ||
fnmatch(name, s->name, 0) == 0) {
if (sfound != NULL) {
*ambiguous = 1;
return (NULL);
}
sfound = s;
}
}
return (sfound);
}
/*
* Lookup a window or return -1 if not found or ambigious. First try as an
* index and if invalid, use fnmatch or leading prefix. Return NULL but fill in
* idx if the window index is a valid number but there is now window with that
* index.
*/
struct winlink *
cmd_lookup_window(struct session *s, const char *name, int *ambiguous)
{
struct winlink *wl, *wlfound;
const char *errstr;
u_int idx;
*ambiguous = 0;
/* First see if this is a valid window index in this session. */
idx = strtonum(name, 0, INT_MAX, &errstr);
if (errstr == NULL) {
if ((wl = winlink_find_by_index(&s->windows, idx)) != NULL)
return (wl);
}
/* Look for exact matches, error if more than one. */
wlfound = NULL;
RB_FOREACH(wl, winlinks, &s->windows) {
if (strcmp(name, wl->window->name) == 0) {
if (wlfound != NULL) {
*ambiguous = 1;
return (NULL);
}
wlfound = wl;
}
}
if (wlfound != NULL)
return (wlfound);
/* Now look for pattern matches, again error if multiple. */
wlfound = NULL;
RB_FOREACH(wl, winlinks, &s->windows) {
if (strncmp(name, wl->window->name, strlen(name)) == 0 ||
fnmatch(name, wl->window->name, 0) == 0) {
if (wlfound != NULL) {
*ambiguous = 1;
return (NULL);
}
wlfound = wl;
}
}
if (wlfound != NULL)
return (wlfound);
return (NULL);
}
/*
* Find a window index - if the window doesn't exist, check if it is a
* potential index and return it anyway.
*/
int
cmd_lookup_index(struct session *s, const char *name, int *ambiguous)
{
struct winlink *wl;
const char *errstr;
u_int idx;
if ((wl = cmd_lookup_window(s, name, ambiguous)) != NULL)
return (wl->idx);
if (*ambiguous)
return (-1);
idx = strtonum(name, 0, INT_MAX, &errstr);
if (errstr == NULL)
return (idx);
return (-1);
}
/* Find the target session or report an error and return NULL. */
struct session * struct session *
cmd_find_session(struct cmd_ctx *ctx, const char *arg) cmd_find_session(struct cmd_ctx *ctx, const char *arg)
{ {
struct session *s; struct session *s;
struct client *c;
char *tmparg;
size_t arglen;
int ambiguous;
/* A NULL argument means the current session. */
if (arg == NULL) if (arg == NULL)
s = cmd_current_session(ctx); return (cmd_current_session(ctx));
else { tmparg = xstrdup(arg);
if ((s = arg_parse_session(arg)) == NULL) {
if (arg != NULL) /* Trim a single trailing colon if any. */
ctx->error(ctx, "session not found: %s", arg); arglen = strlen(tmparg);
else if (arglen != 0 && tmparg[arglen - 1] == ':')
ctx->error(ctx, "no session found"); tmparg[arglen - 1] = '\0';
}
/* Find the session, if any. */
s = cmd_lookup_session(tmparg, &ambiguous);
/* If it doesn't, try to match it as a client. */
if (s == NULL && (c = cmd_lookup_client(tmparg)) != NULL)
s = c->session;
/* If no session found, report an error. */
if (s == NULL) {
if (ambiguous)
ctx->error(ctx, "more than one session: %s", tmparg);
else
ctx->error(ctx, "session not found: %s", tmparg);
} }
xfree(tmparg);
return (s); return (s);
} }
/* Find the target session and window or report an error and return NULL. */
struct winlink * struct winlink *
cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{ {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
int idx; const char *winptr;
char *sessptr = NULL;
int ambiguous = 0;
wl = NULL; /*
if (arg_parse_window(arg, &s, &idx) != 0) { * Find the current session. There must always be a current session, if
ctx->error(ctx, "bad window: %s", arg); * it can't be found, report an error.
*/
if ((s = cmd_current_session(ctx)) == NULL) {
ctx->error(ctx, "can't establish current session");
return (NULL); return (NULL);
} }
if (s == NULL)
s = ctx->cursession; /* A NULL argument means the current session and window. */
if (s == NULL) if (arg == NULL) {
s = cmd_current_session(ctx); if (sp != NULL)
if (s == NULL) *sp = s;
return (NULL); return (s->curw);
}
/* Time to look at the argument. If it is empty, that is an error. */
if (*arg == '\0')
goto not_found;
/* Find the separating colon and split into window and session. */
winptr = strchr(arg, ':');
if (winptr == NULL)
goto no_colon;
winptr++; /* skip : */
sessptr = xstrdup(arg);
*strchr(sessptr, ':') = '\0';
/* Try to lookup the session if present. */
if (*sessptr != '\0') {
if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
goto no_session;
}
if (sp != NULL) if (sp != NULL)
*sp = s; *sp = s;
if (idx == -1) /*
* Then work out the window. An empty string is the current window,
* otherwise try to look it up in the session.
*/
if (*winptr == '\0')
wl = s->curw; wl = s->curw;
else else if ((wl = cmd_lookup_window(s, winptr, &ambiguous)) == NULL)
wl = winlink_find_by_index(&s->windows, idx); goto not_found;
if (wl == NULL)
ctx->error(ctx, "window not found: %s:%d", s->name, idx); if (sessptr != NULL)
xfree(sessptr);
return (wl); return (wl);
no_colon:
/* No colon in the string, first try as a window then as a session. */
if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) {
if (ambiguous)
goto not_found;
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
wl = s->curw;
}
if (sp != NULL)
*sp = s;
return (wl);
no_session:
if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg);
else
ctx->error(ctx, "session not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (NULL);
not_found:
if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg);
else
ctx->error(ctx, "window not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (NULL);
}
/*
* Find the target session and window index, whether or not it exists in the
* session. Return -2 on error or -1 if no window index is specified. This is
* used when parsing an argument for a window target that may not exist (for
* example if it is going to be created).
*/
int
cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{
struct session *s;
const char *winptr;
char *sessptr = NULL;
int idx, ambiguous = 0;
/*
* Find the current session. There must always be a current session, if
* it can't be found, report an error.
*/
if ((s = cmd_current_session(ctx)) == NULL) {
ctx->error(ctx, "can't establish current session");
return (-2);
}
/* A NULL argument means the current session and "no window" (-1). */
if (arg == NULL) {
if (sp != NULL)
*sp = s;
return (-1);
}
/* Time to look at the argument. If it is empty, that is an error. */
if (*arg == '\0')
goto not_found;
/* Find the separating colon. If none, assume the current session. */
winptr = strchr(arg, ':');
if (winptr == NULL)
goto no_colon;
winptr++; /* skip : */
sessptr = xstrdup(arg);
*strchr(sessptr, ':') = '\0';
/* Try to lookup the session if present. */
if (sessptr != NULL && *sessptr != '\0') {
if ((s = cmd_lookup_session(sessptr, &ambiguous)) == NULL)
goto no_session;
}
if (sp != NULL)
*sp = s;
/*
* Then work out the window. An empty string is a new window otherwise
* try to look it up in the session.
*/
if (*winptr == '\0')
idx = -1;
else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) {
if (ambiguous)
goto not_found;
ctx->error(ctx, "invalid index: %s", arg);
idx = -2;
}
if (sessptr != NULL)
xfree(sessptr);
return (idx);
no_colon:
/* No colon in the string, first try as a window then as a session. */
if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) {
if (ambiguous)
goto not_found;
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
idx = -1;
}
if (sp != NULL)
*sp = s;
return (idx);
no_session:
if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg);
else
ctx->error(ctx, "session not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
not_found:
if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg);
else
ctx->error(ctx, "window not found: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
}
/*
* Find the target session, window and pane number or report an error and
* return NULL. The pane number is separated from the session:window by a .,
* such as mysession:mywindow.0.
*/
struct winlink *
cmd_find_pane(struct cmd_ctx *ctx,
const char *arg, struct session **sp, struct window_pane **wpp)
{
struct session *s;
struct winlink *wl;
const char *period;
char *winptr, *paneptr;
const char *errstr;
u_int idx;
/* Get the current session. */
if ((s = cmd_current_session(ctx)) == NULL) {
ctx->error(ctx, "can't establish current session");
return (NULL);
}
if (sp != NULL)
*sp = s;
/* A NULL argument means the current session, window and pane. */
if (arg == NULL) {
*wpp = s->curw->window->active;
return (s->curw);
}
/* Look for a separating period. */
if ((period = strrchr(arg, '.')) == NULL)
goto no_period;
/* Pull out the window part and parse it. */
winptr = xstrdup(arg);
winptr[period - arg] = '\0';
if (*winptr == '\0')
wl = s->curw;
else if ((wl = cmd_find_window(ctx, winptr, sp)) == NULL)
goto error;
/* Find the pane section and look it up. */
paneptr = winptr + (period - arg) + 1;
if (*paneptr == '\0')
*wpp = wl->window->active;
else {
idx = strtonum(paneptr, 0, INT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "pane %s: %s", errstr, paneptr);
goto error;
}
*wpp = window_pane_at_index(wl->window, idx);
if (*wpp == NULL) {
ctx->error(ctx, "no such pane: %u", idx);
goto error;
}
}
xfree(winptr);
return (wl);
no_period:
/* Try as a pane number alone. */
idx = strtonum(arg, 0, INT_MAX, &errstr);
if (errstr != NULL)
goto lookup_window;
/* Try index in the current session and window. */
if ((*wpp = window_pane_at_index(s->curw->window, idx)) == NULL)
goto lookup_window;
return (s->curw);
lookup_window:
/* Try as a window and use the active pane. */
if ((wl = cmd_find_window(ctx, arg, sp)) != NULL)
*wpp = wl->window->active;
return (wl);
error:
xfree(winptr);
return (NULL);
}
/* Replace the first %% or %idx in template by s. */
char *
cmd_template_replace(char *template, const char *s, int idx)
{
char ch;
char *buf, *ptr;
int replaced;
size_t len;
if (strstr(template, "%") == NULL)
return (xstrdup(template));
buf = xmalloc(1);
*buf = '\0';
len = 0;
replaced = 0;
ptr = template;
while (*ptr != '\0') {
switch (ch = *ptr++) {
case '%':
if (*ptr < '1' || *ptr > '9' || *ptr - '0' != idx) {
if (*ptr != '%' || replaced)
break;
replaced = 1;
}
ptr++;
len += strlen(s);
buf = xrealloc(buf, 1, len + 1);
strlcat(buf, s, len + 1);
continue;
}
buf = xrealloc(buf, 1, len + 2);
buf[len++] = ch;
buf[len] = '\0';
}
return (buf);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: colour.c,v 1.6 2009-05-18 15:42:30 nicm Exp $ */ /* $Id: colour.c,v 1.7 2009-09-11 14:13:52 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,13 +18,42 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
const char * /*
colour_tostring(u_char c) * Colour to string conversion functions. Bit 8 of the colour means it is one
* of the 256 colour palette.
*/
void
colour_set_fg(struct grid_cell *gc, int c)
{ {
if (c & 0x100)
gc->flags |= GRID_FLAG_FG256;
gc->fg = c;
}
void
colour_set_bg(struct grid_cell *gc, int c)
{
if (c & 0x100)
gc->flags |= GRID_FLAG_BG256;
gc->bg = c;
}
const char *
colour_tostring(int c)
{
static char s[32];
if (c & 0x100) {
xsnprintf(s, sizeof s, "colour%u", c & ~0x100);
return (s);
}
switch (c) { switch (c) {
case 0: case 0:
return ("black"); return ("black");
@@ -51,6 +80,16 @@ colour_tostring(u_char c)
int int
colour_fromstring(const char *s) colour_fromstring(const char *s)
{ {
const char *errstr;
int n;
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
if (errstr != NULL)
return (-1);
return (n | 0x100);
}
if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0')) if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
return (0); return (0);
if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0')) if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))

View File

@@ -1,4 +1,4 @@
/* $Id: compat.h,v 1.6 2009-07-02 07:30:59 nicm Exp $ */ /* $Id: compat.h,v 1.17 2009-09-03 20:54:39 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -16,11 +16,19 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifndef HAVE_U_INT
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
#endif
#ifndef HAVE_PATHS_H #ifndef HAVE_PATHS_H
#define _PATH_BSHELL "/bin/sh" #define _PATH_BSHELL "/bin/sh"
#define _PATH_TMP "/tmp/" #define _PATH_TMP "/tmp/"
#define _PATH_DEVNULL "/dev/null" #define _PATH_DEVNULL "/dev/null"
#define _PATH_TTY "/dev/tty" #define _PATH_TTY "/dev/tty"
#define _PATH_DEV "/dev/"
#endif #endif
#ifdef HAVE_QUEUE_H #ifdef HAVE_QUEUE_H
@@ -44,6 +52,8 @@
#ifdef HAVE_POLL #ifdef HAVE_POLL
#include <poll.h> #include <poll.h>
#else #else
#define POLLNVAL 0
#define POLLHUP 0
#include "compat/bsd-poll.h" #include "compat/bsd-poll.h"
#endif #endif
@@ -77,6 +87,23 @@
#include "compat/vis.h" #include "compat/vis.h"
#endif #endif
#ifndef HAVE_IMSG
#include "compat/imsg.h"
#endif
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
#endif
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
/* Broken on OS X. */
#undef CMSG_FIRSTHDR
#define CMSG_FIRSTHDR(mhdr) \
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
(struct cmsghdr *)(mhdr)->msg_control : \
(struct cmsghdr *)NULL)
#endif
#ifndef INFTIM #ifndef INFTIM
#define INFTIM -1 #define INFTIM -1
#endif #endif
@@ -115,66 +142,32 @@
} while (0) } while (0)
#endif #endif
#ifndef PASS_MAX
#define PASS_MAX 128
#endif
#ifndef TTY_NAME_MAX #ifndef TTY_NAME_MAX
#define TTY_NAME_MAX 32 #define TTY_NAME_MAX 32
#endif #endif
#ifndef _PW_BUF_LEN
#define _PW_BUF_LEN 1024
#endif
#ifndef HAVE_BZERO
#define bzero(buf, len) memset((buf), 0, (len));
#endif
#ifndef HAVE_STRCASESTR #ifndef HAVE_STRCASESTR
/* strcasestr.c */ /* strcasestr.c */
char *strcasestr(const char *, const char *); char *strcasestr(const char *, const char *);
#endif #endif
#ifndef HAVE_STRTONUM #ifndef HAVE_STRSEP
/* strtonum.c */ /* strsep.c */
long long strtonum(const char *, long long, long long, const char **); char *strsep(char **, const char *);
#endif #endif
#ifndef HAVE_STRLCPY
/* strlcpy.c */
size_t strlcpy(char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCAT
/* strlcat.c */
size_t strlcat(char *, const char *, size_t);
#endif
#ifndef HAVE_DAEMON
/* daemon.c */
int daemon(int, int);
#endif
#ifndef HAVE_FORKPTY
/* forkpty.c */
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
#endif
#ifndef HAVE_ASPRINTF
/* asprintf.c */
int asprintf(char **, const char *, ...);
int vasprintf(char **, const char *, va_list);
#endif
#ifndef HAVE_FGETLN
/* fgetln.c */
char *fgetln(FILE *, size_t *);
#endif
#ifndef HAVE_GETOPT
/* getopt.c */
extern int BSDopterr;
extern int BSDoptind;
extern int BSDoptopt;
extern int BSDoptreset;
extern char *BSDoptarg;
int BSDgetopt(int, char *const *, const char *);
#define getopt(ac, av, o) BSDgetopt(ac, av, o)
#define opterr BSDopterr
#define optind BSDoptind
#define optopt BSDoptopt
#define optreset BSDoptreset
#define optarg BSDoptarg
#endif
#ifndef HAVE_STRTONUM #ifndef HAVE_STRTONUM
/* strtonum.c */ /* strtonum.c */
long long strtonum(const char *, long long, long long, const char **); long long strtonum(const char *, long long, long long, const char **);

View File

@@ -1,4 +1,4 @@
/* $Id: forkpty-aix.c,v 1.2 2009-03-31 22:08:45 nicm Exp $ */ /* $Id: forkpty-aix.c,v 1.4 2009-09-20 18:31:16 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,8 +27,7 @@
#include "tmux.h" #include "tmux.h"
pid_t pid_t
forkpty(int *master, forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
unused char *name, unused struct termios *tio, struct winsize *ws)
{ {
int slave, fd; int slave, fd;
char *path; char *path;
@@ -71,6 +70,8 @@ forkpty(int *master,
fatal("open failed"); fatal("open failed");
close(fd); close(fd);
if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
fatal("tcsetattr failed");
if (ioctl(slave, TIOCSWINSZ, ws) == -1) if (ioctl(slave, TIOCSWINSZ, ws) == -1)
fatal("ioctl failed"); fatal("ioctl failed");

View File

@@ -1,4 +1,4 @@
/* $Id: forkpty-sunos.c,v 1.6 2008-06-23 21:54:48 nicm Exp $ */ /* $Id: forkpty-sunos.c,v 1.8 2009-09-20 18:31:16 nicm Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,8 +27,7 @@
#include "tmux.h" #include "tmux.h"
pid_t pid_t
forkpty(int *master, forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
unused char *name, unused struct termios *tio, struct winsize *ws)
{ {
int slave; int slave;
char *path; char *path;
@@ -63,6 +62,8 @@ forkpty(int *master,
if (ioctl(slave, I_PUSH, "ldterm") == -1) if (ioctl(slave, I_PUSH, "ldterm") == -1)
fatal("ioctl failed"); fatal("ioctl failed");
if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
fatal("tcsetattr failed");
if (ioctl(slave, TIOCSWINSZ, ws) == -1) if (ioctl(slave, TIOCSWINSZ, ws) == -1)
fatal("ioctl failed"); fatal("ioctl failed");
@@ -70,7 +71,7 @@ forkpty(int *master,
dup2(slave, 1); dup2(slave, 1);
dup2(slave, 2); dup2(slave, 2);
if (slave > 2) if (slave > 2)
close(slave); close(slave);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: getopt.c,v 1.1 2009-05-13 22:20:48 nicm Exp $ */ /* $Id: getopt.c,v 1.2 2009-08-09 18:35:38 nicm Exp $ */
/* /*
* Copyright (c) 1987, 1993, 1994 * Copyright (c) 1987, 1993, 1994
@@ -87,7 +87,7 @@ BSDgetopt(nargc, nargv, ostr)
++BSDoptind; ++BSDoptind;
if (BSDopterr && *ostr != ':') if (BSDopterr && *ostr != ':')
(void)fprintf(stderr, (void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname, BSDoptopt); "%s: unknown option -- %c\n", __progname, BSDoptopt);
return (BADCH); return (BADCH);
} }
if (*++oli != ':') { /* don't need argument */ if (*++oli != ':') { /* don't need argument */

303
compat/imsg-buffer.c Normal file
View File

@@ -0,0 +1,303 @@
/* $Id: imsg-buffer.c,v 1.4 2009-09-15 23:59:40 tcunha Exp $ */
/* $OpenBSD: imsg-buffer.c,v 1.2 2009/09/15 18:12:51 jacekm Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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 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/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
int buf_realloc(struct buf *, size_t);
void buf_enqueue(struct msgbuf *, struct buf *);
void buf_dequeue(struct msgbuf *, struct buf *);
struct buf *
buf_open(size_t len)
{
struct buf *buf;
if ((buf = calloc(1, sizeof(struct buf))) == NULL)
return (NULL);
if ((buf->buf = malloc(len)) == NULL) {
free(buf);
return (NULL);
}
buf->size = buf->max = len;
buf->fd = -1;
return (buf);
}
struct buf *
buf_dynamic(size_t len, size_t max)
{
struct buf *buf;
if (max < len)
return (NULL);
if ((buf = buf_open(len)) == NULL)
return (NULL);
if (max > 0)
buf->max = max;
return (buf);
}
int
buf_realloc(struct buf *buf, size_t len)
{
u_char *b;
/* on static buffers max is eq size and so the following fails */
if (buf->wpos + len > buf->max) {
errno = ENOMEM;
return (-1);
}
b = realloc(buf->buf, buf->wpos + len);
if (b == NULL)
return (-1);
buf->buf = b;
buf->size = buf->wpos + len;
return (0);
}
int
buf_add(struct buf *buf, const void *data, size_t len)
{
if (buf->wpos + len > buf->size)
if (buf_realloc(buf, len) == -1)
return (-1);
memcpy(buf->buf + buf->wpos, data, len);
buf->wpos += len;
return (0);
}
void *
buf_reserve(struct buf *buf, size_t len)
{
void *b;
if (buf->wpos + len > buf->size)
if (buf_realloc(buf, len) == -1)
return (NULL);
b = buf->buf + buf->wpos;
buf->wpos += len;
return (b);
}
void *
buf_seek(struct buf *buf, size_t pos, size_t len)
{
/* only allowed to seek in already written parts */
if (pos + len > buf->wpos)
return (NULL);
return (buf->buf + pos);
}
size_t
buf_size(struct buf *buf)
{
return (buf->wpos);
}
size_t
buf_left(struct buf *buf)
{
return (buf->max - buf->wpos);
}
void
buf_close(struct msgbuf *msgbuf, struct buf *buf)
{
buf_enqueue(msgbuf, buf);
}
int
buf_write(struct msgbuf *msgbuf)
{
struct iovec iov[IOV_MAX];
struct buf *buf;
unsigned int i = 0;
ssize_t n;
bzero(&iov, sizeof(iov));
TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
if (i >= IOV_MAX)
break;
iov[i].iov_base = buf->buf + buf->rpos;
iov[i].iov_len = buf->wpos - buf->rpos;
i++;
}
if ((n = writev(msgbuf->fd, iov, i)) == -1) {
if (errno == EAGAIN || errno == ENOBUFS ||
errno == EINTR) /* try later */
return (0);
else
return (-1);
}
if (n == 0) { /* connection closed */
errno = 0;
return (-2);
}
msgbuf_drain(msgbuf, n);
return (0);
}
void
buf_free(struct buf *buf)
{
free(buf->buf);
free(buf);
}
void
msgbuf_init(struct msgbuf *msgbuf)
{
msgbuf->queued = 0;
msgbuf->fd = -1;
TAILQ_INIT(&msgbuf->bufs);
}
void
msgbuf_drain(struct msgbuf *msgbuf, size_t n)
{
struct buf *buf, *next;
for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
buf = next) {
next = TAILQ_NEXT(buf, entry);
if (buf->rpos + n >= buf->wpos) {
n -= buf->wpos - buf->rpos;
buf_dequeue(msgbuf, buf);
} else {
buf->rpos += n;
n = 0;
}
}
}
void
msgbuf_clear(struct msgbuf *msgbuf)
{
struct buf *buf;
while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
buf_dequeue(msgbuf, buf);
}
int
msgbuf_write(struct msgbuf *msgbuf)
{
struct iovec iov[IOV_MAX];
struct buf *buf;
unsigned int i = 0;
ssize_t n;
struct msghdr msg;
struct cmsghdr *cmsg;
union {
struct cmsghdr hdr;
char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf;
bzero(&iov, sizeof(iov));
bzero(&msg, sizeof(msg));
TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
if (i >= IOV_MAX)
break;
iov[i].iov_base = buf->buf + buf->rpos;
iov[i].iov_len = buf->wpos - buf->rpos;
i++;
if (buf->fd != -1)
break;
}
msg.msg_iov = iov;
msg.msg_iovlen = i;
if (buf != NULL && buf->fd != -1) {
msg.msg_control = (caddr_t)&cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = buf->fd;
}
if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
if (errno == EAGAIN || errno == ENOBUFS ||
errno == EINTR) /* try later */
return (0);
else
return (-1);
}
if (n == 0) { /* connection closed */
errno = 0;
return (-2);
}
/*
* assumption: fd got sent if sendmsg sent anything
* this works because fds are passed one at a time
*/
if (buf != NULL && buf->fd != -1) {
close(buf->fd);
buf->fd = -1;
}
msgbuf_drain(msgbuf, n);
return (0);
}
void
buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
{
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
msgbuf->queued++;
}
void
buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
{
TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
if (buf->fd != -1)
close(buf->fd);
msgbuf->queued--;
buf_free(buf);
}

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