352 Commits
2.1 ... 2.2

Author SHA1 Message Date
Thomas Adam
9a4b45dc0f Add CHANGES notes for 2.2 release 2016-04-11 01:00:35 +01:00
Thomas Adam
ad2532c3f4 Merge branch 'obsd-master' 2016-04-04 18:01:11 +01:00
nicm
075c086d29 fatalx() not fatal(). 2016-04-04 16:19:43 +00:00
Nicholas Marriott
7b8dcbaa86 Merge branch 'master' of github.com:tmux/tmux 2016-04-03 23:55:56 +01:00
Nicholas Marriott
75b2c1693e Add --disable-utempter to build without it. 2016-04-03 23:55:38 +01:00
Thomas Adam
1394420c37 Merge branch 'obsd-master' 2016-03-30 16:01:19 +01:00
nicm
ec82fcdfea Bump the listen() backlog up, some people have scripts that run up a lot
of clients quickly.
2016-03-30 13:20:07 +00:00
Nicholas Marriott
5658b628b9 Look for utempter_add_record to be sure we have the new utempter API, the old
utempter API was also using utempter.h.
2016-03-26 20:17:17 +00:00
Nicholas Marriott
b429a00cce Add to TODO. 2016-03-20 08:14:14 +00:00
Thomas Adam
410ccce4a3 Merge branch 'obsd-master' 2016-03-18 16:01:15 +00:00
nicm
312a7a1e62 Make scrolling behaviour more sensible and maintain cursor position, as
if the same had been done line-by-line. From Michal Mazurek.
2016-03-18 14:27:24 +00:00
Thomas Adam
ed598e9fe1 Merge branch 'obsd-master' 2016-03-18 08:01:18 +00:00
nicm
fa97b0a95b Instead of reusing MouseUp at the finish of a drag, add a new key
MouseDragEnd. It can be useful to bind them separately in copy mode.
2016-03-18 07:28:27 +00:00
Nicholas Marriott
3dfc79fb09 Tweak a comment. 2016-03-17 15:11:40 +00:00
Thomas Adam
5fc5c03dad Merge branch 'obsd-master'
Conflicts:
	tmux.c
2016-03-05 17:58:12 +00:00
nicm
0d6de44a37 If setlocale("en_US.UTF-8") succeeds, then don't do the check for UTF-8
locale since if it isn't UTF-8 the system is broken anyway. If it fails,
try "" and check for UTF-8 with nl_langinfo(CODESET) rather than
wcwidth(). Based on a diff from schwarze@, nl_langinfo also suggested by
stsp@.
2016-03-05 16:08:38 +00:00
Thomas Adam
81f78f0da7 Merge branch 'obsd-master' 2016-03-05 10:01:09 +00:00
nicm
c38e0a4bbc Do not use c->cwd or s->cwd if it is NULL, found by Ben Boeckel. 2016-03-05 07:47:52 +00:00
nicm
1f0b317088 Although we always have en_US.UTF-8 on OpenBSD, some platforms do not,
so fall back to setlocale(LC_CTYPE, ""). tmux requires a UTF-8 locale,
so check with wcwidth() on a UTF-8 character after setlocale().
2016-03-05 07:44:31 +00:00
Thomas Adam
6c35d17800 Merge branch 'obsd-master' 2016-03-03 16:01:11 +00:00
nicm
df0983af39 show-* and set-* need to handle a missing target. 2016-03-03 14:15:22 +00:00
nicm
fa81d838da Accept clients as sessions in cmd_find_get_session. 2016-03-03 14:14:46 +00:00
Thomas Adam
45d62482da Merge branch 'obsd-master' 2016-03-03 14:01:10 +00:00
nicm
bcb41a09b3 RGB colours shouldn't be mixed up with aixterm colours, return before
that happens when working out if they are supported.
2016-03-03 12:58:15 +00:00
Nicholas Marriott
9e2fbb31ec +wchar.h 2016-03-02 18:19:13 +00:00
Nicholas Marriott
985504ff2c Merge branch 'next' 2016-03-02 18:16:51 +00:00
Thomas Adam
e304673c65 Merge branch 'obsd-master'
Conflicts:
	utf8.c
2016-03-02 18:10:51 +00:00
nicm
b8a102d26f Handle wcwidth() and mbtowc() failures in better style and drop
characters where we can't find the width (wcwidth() fails) on input, the
same as we drop invalid UTF-8. Suggested by schwarze@.
2016-03-02 15:36:02 +00:00
nicm
d980d965dd Limit x, y and b to 0x7ff for UTF-8 mouse input, suggested by schwarze@. 2016-03-02 15:33:36 +00:00
nicm
f0239a8fe9 Remove some more unused variables, and use RB_FOREACH_SAFE in
key_bindings_unref_table.
2016-03-01 12:06:07 +00:00
nicm
2e4503ad4e Redraw status on mode entry and exit. 2016-03-01 12:05:15 +00:00
nicm
54ea8f74ae When a mouse drag is finished, fire a MouseUp key press, instead of
doing the drag end in code. From Stephen Coakley.
2016-03-01 12:04:43 +00:00
nicm
e647eeb0c9 Remove unused variables, from Michal Mazurek. 2016-03-01 12:02:54 +00:00
nicm
26945d7956 Use system wcwidth() instead of carrying around UTF-8 width tables. 2016-03-01 12:02:08 +00:00
nicm
c7851e0ee7 Fix break-pane synopsis and some other tmux.1 bits. 2016-03-01 11:58:45 +00:00
Nicholas Marriott
a011b67f56 Remove unused variables. 2016-02-19 16:45:35 +00:00
Nicholas Marriott
c3f93e7178 Add to TODO. 2016-02-19 16:45:15 +00:00
Nicholas Marriott
931b1c6d59 Merge branch 'master' into next 2016-02-19 13:37:18 +00:00
Nicholas Marriott
e9d369a09e Fixed fgetln(3) implementation (from Joerg Jung) which does not depend on *BSD
fgets(3) semantics.
2016-02-19 13:35:46 +00:00
Nicholas Marriott
6adf561507 Redraw status on mode entry and exit. 2016-02-19 13:29:59 +00:00
Nicholas Marriott
95adc0e6ba When a mouse drag is finished, fire a MouseUp key press, instead of doing the
drag end in code. From Stephen Coakley.
2016-02-19 13:28:03 +00:00
Nicholas Marriott
02753ba9ea Remove unused variables, from Michal Mazurek. 2016-02-19 13:15:22 +00:00
Nicholas Marriott
acc1090e77 Use system wcwidth() instead of carrying around UTF-8 width tables. 2016-02-19 13:14:17 +00:00
Nicholas Marriott
fc864529f5 Remove malloc_options debug bit (already gone from OpenBSD). 2016-02-19 13:11:10 +00:00
Nicholas Marriott
782dd941da Fire SIGCHLD after utempter_add_record since it probably eats it. 2016-02-17 23:21:58 +00:00
Thomas Adam
ba8290aeae Merge branch 'obsd-master' 2016-02-12 14:01:14 +00:00
nicm
4f6bc0a0a9 Expand client formats in run-shell. 2016-02-12 12:24:52 +00:00
Thomas Adam
f7c8f1ae29 xmalloc: define __bounded__ where necessary 2016-02-07 00:04:46 +00:00
Thomas Adam
ba97ae1737 EXTRA_DIST: add example_tmux.conf / xmalloc.h 2016-02-06 19:04:21 +00:00
Thomas Adam
7669cfb330 Merge branch 'obsd-master' 2016-02-05 12:01:10 +00:00
nicm
bc0c9c7920 Do not wrap cursor at start or end of history, from Michal Mazurek. 2016-02-05 10:20:06 +00:00
Nicholas Marriott
07c23ccc05 Merge branch 'master' of github.com:tmux/tmux 2016-02-05 10:08:55 +00:00
Nicholas Marriott
2130a07b70 Add to TODO. 2016-02-05 10:08:39 +00:00
Thomas Adam
26f899be10 Merge branch 'obsd-master' 2016-02-04 16:01:13 +00:00
nicm
bdb8bb790e Set up -t flag properly when passing new-session -A off to
attach-session, GitHub issue 295.
2016-02-04 14:11:20 +00:00
Thomas Adam
8760f877e1 Merge branch 'obsd-master' 2016-01-31 16:01:09 +00:00
nicm
97882f9ce2 Clear RGB flags during selection. 2016-01-31 14:11:49 +00:00
Thomas Adam
5fce21728e Merge branch 'obsd-master' 2016-01-31 12:01:09 +00:00
nicm
fa64b89ad7 Whoops, need this for the previous reverse trim commit too. 2016-01-31 09:57:41 +00:00
nicm
49e9f93738 Add RGB escape sequences for capture-pane -e. 2016-01-31 09:57:09 +00:00
nicm
8028560f82 Support negative trim values (#{=-10:pane_title}) to trim from the end,
suggested by Kevin Brubeck Unhammer.
2016-01-31 09:54:46 +00:00
nicm
225a384dbb Fix new-session with -t after command flags changes, reported by Michael Graczyk. 2016-01-31 09:52:01 +00:00
Nicholas Marriott
404379049a examples/ has gone, so delete some text about it. 2016-01-29 15:45:32 +00:00
Nicholas Marriott
2a1bb91bf7 Remove old examples in favour of one example configuration file. 2016-01-29 14:53:28 +00:00
Nicholas Marriott
a33bb3e876 Link to the bash(1) completion file from README rather than including it in
examples.
2016-01-29 14:40:30 +00:00
Thomas Adam
8cf1504ba6 Merge branch 'obsd-master' 2016-01-29 12:01:16 +00:00
nicm
427b820426 Support for RGB colour, using the extended cell mechanism to avoid
wasting unnecessary space. The 'Tc' flag must be set in the external
TERM entry (using terminal-overrides or a custom terminfo entry), if not
tmux will map to the closest of the 256 or 16 colour palettes.

Mostly from Suraj N Kurapati, based on a diff originally by someone else.
2016-01-29 11:13:56 +00:00
Nicholas Marriott
1d6bd50343 libevent.org URL. 2016-01-29 10:58:08 +00:00
Nicholas Marriott
ca29dc9abc Update my email address. 2016-01-19 18:07:25 +00:00
Thomas Adam
dc42c35f1f Merge branch 'obsd-master' 2016-01-19 18:01:15 +00:00
nicm
b5b5221c13 Split out getting the current state from the target search so it can be
replaced if we already know the current.
2016-01-19 16:01:30 +00:00
nicm
995af0e2b7 I no longer use my SourceForge address so replace it. 2016-01-19 15:59:12 +00:00
Thomas Adam
5d21faa99c Merge branch 'obsd-master' 2016-01-16 02:01:10 +00:00
nicm
c9815307eb Add hooks for alerts (bell, silence, activity), from Thomas Adam. 2016-01-16 00:36:53 +00:00
Thomas Adam
506adf3764 Merge branch 'obsd-master' 2016-01-15 12:01:11 +00:00
nicm
d551ab8e5c Clear the environment properly by looping until it is empty rather than
looping over it (which may skip entries), from Brad King.
2016-01-15 11:33:41 +00:00
nicm
68d797587e A couple of missing printflike attributes, from Andrey Starodubtsev. 2016-01-15 11:31:47 +00:00
Thomas Adam
ea9873e60e Merge branch 'obsd-master' 2016-01-02 18:01:12 +00:00
nicm
cfb78654c2 clock-mode needs CMD_PANE. 2016-01-02 17:16:25 +00:00
Thomas Adam
051cf5437a Merge branch 'obsd-master' 2016-01-01 10:01:11 +00:00
nicm
311be04d61 Don't rely on a calculation wrapping when applying message-limit, and
break out of the loop early. From Nicolas Viennot.
2016-01-01 08:04:20 +00:00
Thomas Adam
5e59c301b7 Merge branch 'obsd-master' 2015-12-31 20:01:09 +00:00
nicm
7e67db79dc Remove an extra unzoom call which was probably a merge error. 2015-12-31 18:34:47 +00:00
nicm
f84d32ca5e Use saved pipe buffer offset when writing to pipe, from Nicolas Viennot. 2015-12-31 18:14:13 +00:00
Thomas Adam
5dd0e82809 Merge branch 'obsd-master' 2015-12-28 16:01:09 +00:00
nicm
2a1f27eb1a Couple of trivial style nits. 2015-12-28 14:02:52 +00:00
Nicholas Marriott
e15a8a7c46 Keith Smiley is going to maintain the vim syntax file. 2015-12-24 16:59:12 +00:00
Thomas Adam
ed65535c41 Merge branch 'obsd-master' 2015-12-23 02:01:14 +00:00
nicm
60cbdf9ccd Repair switch-client -l and switch-client with a window target. 2015-12-23 00:12:57 +00:00
Thomas Adam
5083e93957 Merge branch 'obsd-master' 2015-12-21 10:01:08 +00:00
nicm
f2ec911b8a Detach the right session with -d. 2015-12-21 09:20:13 +00:00
Nicholas Marriott
c83d6ee0b1 Merge branch 'master' of github.com:tmux/tmux 2015-12-20 11:26:12 +00:00
Nicholas Marriott
83c96d2685 No need to set cwd on Cygwin now, from Yuya Adachi. 2015-12-20 11:25:13 +00:00
Thomas Adam
58b3d66229 Merge branch 'obsd-master' 2015-12-19 10:01:08 +00:00
nicm
bdbec099cc Make input off flag (selectp -d) apply to synchronize-panes too. 2015-12-19 08:43:04 +00:00
Thomas Adam
2ad9caad3f Merge branch 'obsd-master' 2015-12-18 00:01:08 +00:00
nicm
a337403868 As well as setting up the state, actually use it in cmd_find_target. 2015-12-17 23:08:22 +00:00
Thomas Adam
e0cae08c04 Merge branch 'obsd-master' 2015-12-17 00:01:08 +00:00
nicm
99e9a4c786 send-keys -R should reset the input parser to ground state (so it can be
used to escape from, for example, printf '\033]2;').
2015-12-16 22:05:35 +00:00
Thomas Adam
7c94dae702 Merge branch 'obsd-master' 2015-12-16 22:01:08 +00:00
nicm
021c64310d Add infrastructure to work out the best target given a pane or window
alone and use it to add pane_died and pane_exited hooks.
2015-12-16 21:50:37 +00:00
nicm
8eb1a7d5dc showenv and setenv need to be CANFAIL. 2015-12-16 21:47:00 +00:00
Thomas Adam
f7a6482e6b Merge branch 'obsd-master' 2015-12-15 16:01:12 +00:00
nicm
909b737289 Copy state directly rather than dereferencing wl (which could be NULL). 2015-12-15 14:32:55 +00:00
Thomas Adam
e5caf64815 Merge branch 'obsd-master' 2015-12-15 14:01:12 +00:00
nicm
ac9778395f Some hooks API changes to fire a hook while waiting another cmdq and
infrastructure that will be needed soon.
2015-12-15 13:43:07 +00:00
Thomas Adam
1a33ea9671 Merge branch 'obsd-master' 2015-12-15 02:01:14 +00:00
nicm
9d88d82d5e Allow list-keys and list-commands to be run without a running server. 2015-12-15 00:52:17 +00:00
nicm
6f417ec943 We changed somewhat recently to us the pty when tmux was run inside
itself to work out the current pane. This is confusing in many cases
(particularly notable is that "tmux neww\; splitw" would not split the
new window), and the few advantages do not make up for the confusion.

So drop this behaviour and return to using the current window and pane;
keep the pty check but only use it to limit the list of possible current
sessions.
2015-12-15 00:45:02 +00:00
nicm
56d097cfe0 Don't copy marked pane when can just point to it. 2015-12-15 00:11:24 +00:00
Thomas Adam
6ab17e3e15 Merge branch 'obsd-master' 2015-12-15 00:01:08 +00:00
nicm
12da13c9d1 Make the marked pane a cmd_find_state. 2015-12-15 00:00:01 +00:00
nicm
d5999f8b5c Use cmd_find_clear_state instead of an extra function doing the same. 2015-12-14 23:30:58 +00:00
Thomas Adam
bc6137f9e4 Merge branch 'obsd-master' 2015-12-14 01:30:15 +00:00
nicm
a585a1b81a Remove some stray debug code. 2015-12-14 00:32:19 +00:00
nicm
a3129fd4e8 Instead of combined flags for -c, -s, -t, split into different sets
using an enum and simplify the parsing code.
2015-12-14 00:31:54 +00:00
Thomas Adam
5caec3020d Merge branch 'obsd-master' 2015-12-13 23:46:58 +00:00
Thomas Adam
f4adcfa0e2 Merge branch 'obsd-master' 2015-12-13 22:01:08 +00:00
nicm
ecfeee2e82 Use member names in cmd_entry definitions so I stop getting confused
about the order.
2015-12-13 21:53:57 +00:00
nicm
899bee0056 Actually I thought cmd_get_state_client was unnecessary but it will be
needed.
2015-12-13 21:17:37 +00:00
Thomas Adam
00da99f2c4 Merge branch 'obsd-master' 2015-12-13 20:01:09 +00:00
nicm
72948d9f1d -c needs to be able for fail for display-message. 2015-12-13 18:31:47 +00:00
nicm
66d1193a00 Remove an unnecessary function. 2015-12-13 18:27:47 +00:00
nicm
fd47084224 show-options and environment need CANFAIL flag. 2015-12-13 18:15:13 +00:00
Thomas Adam
d37a580085 Merge branch 'obsd-master' 2015-12-13 18:01:11 +00:00
nicm
50f8ead4e6 Don't log an error when doing the first check for move-window. 2015-12-13 17:58:26 +00:00
nicm
9f5aca62a9 Use struct cmd_find_state directly and remove cmd_state_flag, also
change so that winlink is set even if an index is too.
2015-12-13 17:55:14 +00:00
nicm
9b7697db62 Change cmd_find_target to use a state struct from the caller. 2015-12-13 16:44:35 +00:00
nicm
208e2dad1e If command returns error, report it. 2015-12-13 16:11:42 +00:00
Thomas Adam
ae5ddfdc1a Merge branch 'obsd-master' 2015-12-13 16:01:13 +00:00
nicm
ff599f4004 Remove the cmd_find_{session,window,pane,index} functions (which are
just wrappers around cmd_find_target) and just use cmd_find_target
directly.
2015-12-13 15:32:12 +00:00
nicm
9d191a6093 Move logging into cmd_find_target rather than each function. 2015-12-13 15:00:37 +00:00
nicm
4a4daf1303 Instead of every command resolving the target (-t or -s) itself, prepare
the state (client, session, winlink, pane) for it it before entering the
command. Each command provides some flags that tell the prepare step
what it is expecting.

This is a requirement for having hooks on commands (for example, if you
hook "select-window -t1:2", the hook command should to operate on window
1:2 not whatever it thinks is the current window), and should allow some
other target improvements.

The old cmd_find_* functions remain for the moment but that layer will
be dropped later.

Joint work with Thomas Adam.
2015-12-13 14:32:38 +00:00
Nicholas Marriott
92f187d1c2 Need to use pkg-config --static when doing a static build. 2015-12-12 22:04:25 +00:00
Thomas Adam
845a664bb2 Merge branch 'obsd-master' 2015-12-12 20:01:15 +00:00
nicm
5ed17e84fa Add key-table option to set the default key table for a session, allows
different key bindings for different sessions and a few other things.
2015-12-12 18:32:24 +00:00
nicm
6a50cf89b4 Return after changing key table. 2015-12-12 18:28:47 +00:00
nicm
39cf9c9d31 Allow prefix and prefix2 to be set to None to disable (useful if you
would rather bind the prefix in the root table).
2015-12-12 18:19:00 +00:00
Nicholas Marriott
5a5db02b85 Merge branch 'master' of github.com:tmux/tmux 2015-12-11 19:59:08 +00:00
Nicholas Marriott
38cc1a1843 Look for ncurses with PKG_CONFIG, and remove libtinfo because it just causes
confusion.
2015-12-11 19:58:41 +00:00
Thomas Adam
2a6b215328 Merge branch 'obsd-master' 2015-12-11 18:01:11 +00:00
nicm
88bc8f3528 Style nits and line wrapping of function declarations. 2015-12-11 16:37:21 +00:00
nicm
f2be3ad46f Mention {src,dst}-{window,pane} where we define target-{window,pane}. 2015-12-11 16:27:01 +00:00
Thomas Adam
2a3456cd3b Merge branch 'obsd-master' 2015-12-11 16:01:16 +00:00
nicm
bd5918760e We cannot do hooks_find and then hooks_remove because it might have come
from the parent (global) tree, instead make it remove by name like options.

While here, also tidy up a few bits of options and hooks handling (use
RB_FOREACH_SAFE, and a helper function for the free).
2015-12-11 15:46:57 +00:00
Thomas Adam
4909a70174 Merge branch 'obsd-master' 2015-12-11 13:24:45 +00:00
nicm
d7e11d0af7 Check alerts when session changes, from Patrick Palka. 2015-12-11 12:39:47 +00:00
nicm
01831da5f5 Add cmdq as an argument to format_create and add a format for the
command name (will also be used for more later).
2015-12-11 12:27:36 +00:00
Thomas Adam
af8134a6ff Merge branch 'obsd-master' 2015-12-08 10:01:16 +00:00
Nicholas Marriott
a988c36ccb Add to .mailmap, and sort. 2015-12-08 08:46:06 +00:00
nicm
e0f26dcda3 Remove format_create_flags and just pass flags to format_create. 2015-12-08 08:34:18 +00:00
nicm
8f671d3eef Spacing nits. 2015-12-08 08:14:04 +00:00
Thomas Adam
3182728b70 Merge branch 'obsd-master' 2015-12-08 07:12:13 +00:00
Thomas Adam
5862f59ed7 Conflicts:
Makefile
2015-12-08 07:11:09 +00:00
jmc
1f94274b92 Ed was meant to be El; 2015-12-08 06:42:07 +00:00
nicm
d2fb0efcd1 Add hooks infrastructure, basic commands (set-hook, show-hooks) and a
couple of not very useful client hooks. This will eventually let
commands be run at various points and on notifications. Joint work with
Thomas Adam.
2015-12-08 01:10:31 +00:00
mmcc
dbfce2a4d8 Use ^= instead of a verbose alternative. ok nicm@ 2015-12-08 00:51:17 +00:00
Nicholas Marriott
98994a8bb1 termios(4) 2015-12-08 00:49:10 +00:00
Nicholas Marriott
b580a55191 pty(7) -> pty(4) 2015-12-08 00:48:22 +00:00
Nicholas Marriott
ff16836d1d pty is in section 4 2015-12-08 00:47:27 +00:00
Nicholas Marriott
5411033f66 Update tmux.vim from Teubel Gyorgy. 2015-12-07 12:54:34 +00:00
Nicholas Marriott
8383409e88 Merge branch 'master' of github.com:tmux/tmux 2015-12-07 12:51:20 +00:00
Nicholas Marriott
d20a3ef57c Update .mailmap file. 2015-12-07 12:51:06 +00:00
Thomas Adam
bac8c72381 Merge branch 'obsd-master' 2015-12-07 10:01:09 +00:00
nicm
b9563340b7 Fix bell indicators across detach, reported by Torbjorn Lonnemark, diff
from Thomas Adam.
2015-12-07 09:47:41 +00:00
Thomas Adam
8ae9329aa8 Merge branch 'obsd-master' 2015-12-05 14:01:09 +00:00
claudio
0417f1f2be EAGAIN handling for imsg_read. OK henning@ benno@ 2015-12-05 13:18:24 +00:00
Nicholas Marriott
4d5cab4085 Merge branch 'master' of github.com:tmux/tmux 2015-12-03 14:43:33 +00:00
Nicholas Marriott
3cdb2f0bb7 Add to TODO. 2015-12-03 14:43:24 +00:00
Thomas Adam
66bad2e979 Merge branch 'obsd-master' 2015-12-03 00:01:08 +00:00
nicm
7236838dea Mark new active pane changed after pane lost in window, and after
break-pane. Reported by tim@.
2015-12-02 23:09:22 +00:00
Thomas Adam
eb5ee80c74 Merge branch 'obsd-master' 2015-12-01 10:01:13 +00:00
nicm
a785a7f700 Do not deref wp if window_get_active_at returns NULL which can happen on
very large terminals, from Michael Graczyk.
2015-12-01 09:41:03 +00:00
Thomas Adam
742976893e Merge branch 'obsd-master' 2015-11-29 18:01:08 +00:00
guenther
1d331c7e62 Delete a duplicated line
ok jmc@
2015-11-29 17:06:59 +00:00
Thomas Adam
9fe8b28746 Merge branch 'obsd-master' 2015-11-27 15:41:28 +00:00
nicm
6a2ca34216 Do not set a limit on the length of commands when printing them. 2015-11-27 15:06:43 +00:00
Nicholas Marriott
3b83bda29c Add to TODO. 2015-11-25 23:35:24 +00:00
Thomas Adam
a1bc339340 log_open() isn't conditional on proctitle 2015-11-25 16:51:17 +00:00
Thomas Adam
260de2cb5e Remove logfile() 2015-11-25 16:48:47 +00:00
Thomas Adam
890d8da2e3 Merge branch 'obsd-master'
Conflicts:
	log.c
	proc.c
	tmux.c
2015-11-25 16:37:30 +00:00
nicm
ac8678aefe Don't print error if none to print. 2015-11-25 07:58:55 +00:00
nicm
62d3af17f9 Make environ_set va_args and use it to tidy up some calls. Also add a
missing word in manpage (from jmc).
2015-11-24 23:46:15 +00:00
nicm
3ff46b2e43 Shell command from -c doesn't have to be global, pass it as an argument. 2015-11-24 23:22:51 +00:00
nicm
dca93c56e0 Do lock failures slightly better, return a special value so we don't
unlink the wrong thing.
2015-11-24 23:01:51 +00:00
nicm
73e30cbda8 Actually show something (even if it not that helpful) if the server
fails to start (for example if it can't create the socket), rather than
hanging or showing nothing.
2015-11-24 22:45:44 +00:00
nicm
c18fbefe93 Document socket_path format. 2015-11-24 22:27:59 +00:00
nicm
c913fb99b6 Tidy the code that works out the socket path, and just use the full path
in the global socket_path rather than copying it.
2015-11-24 22:27:22 +00:00
nicm
8976dac9e0 Remove malloc_options DEBUG bit. 2015-11-24 22:09:53 +00:00
nicm
bef217b241 Switch a fprintf to a fatal, and wrap some long lines. 2015-11-24 22:04:36 +00:00
nicm
1e2df2d464 Remove the -I part of show-messages which isn't really that useful; the
server start time can now be accessed with a new start_time format (use:
tmux display -p '#{t:start_time}')
2015-11-24 21:52:06 +00:00
nicm
9fd3318dd8 All kill-session -C to clear alerts in all windows, suggested by Aaron
U'Ren.
2015-11-24 21:50:06 +00:00
nicm
4e3015a892 Log some system and libevent information at startup. 2015-11-24 21:32:36 +00:00
nicm
bdbbd9711c Show libevent version in showmsgs -I. 2015-11-24 21:23:44 +00:00
nicm
9cccb8c115 Make the log stuff a bit tidier with some helper functions. 2015-11-24 21:19:46 +00:00
nicm
4ec61bef46 Fix usage of detach-client. 2015-11-24 20:40:51 +00:00
Nicholas Marriott
0a2ef2b932 Merge branch 'master' of github.com:tmux/tmux 2015-11-24 18:50:24 +00:00
Nicholas Marriott
7b085136a7 -sys/queue.h in proc.c, and nuke the unnecessary C++ header guards stuff and
sys/cdefs.h in vis.h (it causes problems on some platforms). Reported by
someone on GitHub, issue 212.
2015-11-24 18:48:07 +00:00
Thomas Adam
534f9e3ab1 Merge branch 'obsd-master' 2015-11-24 10:01:13 +00:00
nicm
b32ce34cf2 Don't allow options in table without scope set. 2015-11-24 09:34:55 +00:00
Thomas Adam
3f47ff6ecd Merge branch 'obsd-master' 2015-11-24 00:01:16 +00:00
nicm
2adf3f42ee Partly revert previous, it is harmless to keep support for UTF-8 mouse
mode inside tmux, just no longer support it for tmux itself.
2015-11-23 23:47:57 +00:00
Thomas Adam
b642b3c8e3 Merge branch 'obsd-master' 2015-11-23 21:21:12 +00:00
Thomas Adam
d63de1e407 Merge branch 'obsd-master'
Conflicts:
	server.c
	tmux.c
2015-11-23 21:20:54 +00:00
nicm
32e510bd70 Remove support for the UTF-8 mouse extension. This was a briefly used,
poor idea that was fairly quickly replaced by SGR mouse input (which is
now widespread). It is impossible to tell the difference between UTF-8
and non-UTF-8 mouse input; since the mouse-utf8 option was removed tmux
has not handled it correctly in any case; and it is ridiculous to have
three different forms of mouse input.
2015-11-23 20:53:09 +00:00
nicm
28e72ae34d Don't leak extddata, memset after freeing it, not before. From Patrick
Palka.
2015-11-22 19:42:57 +00:00
nicm
01a2ddf3f8 Add getpw to pledge, makes tmux work in YP environments, discovered by
matthieu, ok deraadt
2015-11-22 19:41:19 +00:00
tim
4fcc02ee9d If display-time is set to 0, show status messages until a key is pressed;
OK nicm@
2015-11-22 18:28:01 +00:00
Thomas Adam
78a00c845c Merge branch 'obsd-master'
Conflicts:
	tmux.h
2015-11-21 14:24:33 +00:00
Nicholas Marriott
2c482939fd Move tmux.h below system includes. 2015-11-21 08:03:18 +00:00
nicm
933929cd62 Memory leaks and an uninitialized part of utf8_data, from Patrick Palka. 2015-11-20 22:02:54 +00:00
nicm
40fefe2cbc The alerts callback should be fired for bells even if bell-action is
none because it also affects the status line bell indicator (and
bell-action does not). Fixes a problem reported by tim@.
2015-11-20 16:33:46 +00:00
nicm
fce56c56ef Instead of separate tables for different types of options, give each
option a scope type (server, session, window) in one table.
2015-11-20 12:01:19 +00:00
nicm
374e273df5 Only assume pasting with at least two characters, reduces problems for
people who can type ^B c very fast, or who are using tmux inside
something else that buffers.
2015-11-19 22:46:46 +00:00
Thomas Adam
cf688db4b5 Merge branch 'obsd-master' 2015-11-19 16:01:12 +00:00
nicm
98967c5ec9 The activity flag could already be set, so queue the callback always (if
not already queued) rather than only if the flag is being added. Fixes a
problem reported by tim@
2015-11-19 14:55:25 +00:00
Thomas Adam
45b4e337cb Merge branch 'obsd-master' 2015-11-18 18:01:13 +00:00
nicm
82760a9960 Use format_expand_time for display-message. 2015-11-18 16:49:13 +00:00
Nicholas Marriott
c15487318b unused -> __unused. 2015-11-18 16:45:44 +00:00
Nicholas Marriott
a58eaec540 Merge branch 'master' of github.com:tmux/tmux 2015-11-18 16:42:25 +00:00
Thomas Adam
7fe8edc396 Merge branch 'obsd-master' 2015-11-18 16:01:23 +00:00
Nicholas Marriott
8b4b3ff4fc Add __unused, will be needed shortly. 2015-11-18 14:37:08 +00:00
nicm
577c0e3e5a Use __unused rather than rolling our own. 2015-11-18 14:27:44 +00:00
nicm
5a5b950e8b Add s/foo/bar/: prefix for formats to substitute bar for foo. 2015-11-18 14:13:55 +00:00
Nicholas Marriott
f8a1f8843c Add -Wno-attributes. 2015-11-18 14:10:48 +00:00
Nicholas Marriott
9bba26f8c5 Add reallocarray prototype. 2015-11-18 14:09:17 +00:00
Thomas Adam
8fa822b521 Merge branch 'obsd-master' 2015-11-18 14:01:12 +00:00
nicm
64571368dc Sync the entire xmalloc.[ch] with the other users, but with the addition
of xrealloc, xvasprintf, xvsnprintf.
2015-11-18 13:06:54 +00:00
Nicholas Marriott
93742ed5df Merge branch 'master' of github.com:tmux/tmux 2015-11-18 12:55:22 +00:00
Nicholas Marriott
a77960c540 Add reallocarray to compat. 2015-11-18 12:54:29 +00:00
Thomas Adam
4b703d3049 Merge branch 'obsd-master' 2015-11-18 10:01:11 +00:00
nicm
ca5e6bf5f2 Don't update activity time twice for new sessions, and add some logging. 2015-11-18 09:22:29 +00:00
Thomas Adam
44cad8f4ed Merge branch 'obsd-master' 2015-11-17 20:01:12 +00:00
tobias
d0505fd042 Merge xmalloc.[ch] files across base, skipping OpenSSH for now.
ok nicm
2015-11-17 18:25:03 +00:00
Thomas Adam
349a62ed4f Merge branch 'obsd-master' 2015-11-17 00:01:09 +00:00
nicm
775fb562bd 0x7f is a valid key. 2015-11-16 22:57:51 +00:00
Thomas Adam
1686a15fb6 Merge branch 'obsd-master' 2015-11-16 00:01:10 +00:00
nicm
661d0dfac9 Make key_code unsigned long long not uint64_t which is more portable for
printf formats, and move UTF8_SIZE define down to near the rest of the
UTF-8 bits.
2015-11-15 22:50:38 +00:00
Thomas Adam
8213558cc7 Merge branch 'obsd-master'
Conflicts:
	server.c
	tmux.c
2015-11-15 22:49:25 +00:00
nicm
a582b62287 Accidentally turned off pledge, turn it back on. 2015-11-15 14:32:48 +00:00
Thomas Adam
bb820fa761 Merge branch 'obsd-master' 2015-11-14 14:01:08 +00:00
nicm
14d90e4901 The character is an int so use %x not %hhx. 2015-11-14 12:20:19 +00:00
nicm
3db0d50df4 The private use area at U+E000 to U+F8FF is not very useful if it is
width 0, make it width 1 instead.
2015-11-14 12:03:23 +00:00
Thomas Adam
f12d7f0d4b Merge branch 'obsd-master' 2015-11-14 12:01:09 +00:00
nicm
205d15e82d All these return values from utf8_* are confusing, use an enum. 2015-11-14 11:45:43 +00:00
Thomas Adam
7b4b78b419 Merge branch 'obsd-master' 2015-11-14 11:38:52 +00:00
Thomas Adam
7b749eff35 Merge branch 'obsd-master'
Conflicts:
	server.c
	tmux.c
2015-11-14 11:38:30 +00:00
nicm
f401791a56 Rename a variable in utf8_combine for consistency and use 0xfffd for
unknown Unicode.
2015-11-14 11:13:44 +00:00
nicm
dab63b029e Couple of assignments to remove compiler warnings. 2015-11-14 10:57:59 +00:00
nicm
64333e3ef8 Be more strict about invalid UTF-8. 2015-11-14 10:56:31 +00:00
nicm
c56b81a2ce Push stdout and stderr to clients more aggressively, and add an event to
continue if the send fails.
2015-11-14 09:41:06 +00:00
Nicholas Marriott
23266e8e09 Merge branch 'master' of github.com:tmux/tmux 2015-11-14 09:04:41 +00:00
Nicholas Marriott
31d880f751 Update the TODO file. 2015-11-14 09:04:13 +00:00
nicm
908e6bb68f Log more of UTF-8 input. 2015-11-14 08:25:12 +00:00
Thomas Adam
276ca5f04c Merge branch 'obsd-master' 2015-11-13 18:01:13 +00:00
nicm
c4893d8efd Log option names in fatal() for missing option. 2015-11-13 16:06:43 +00:00
Nicholas Marriott
1016f112bf Merge branch 'master' of github.com:tmux/tmux 2015-11-13 16:06:11 +00:00
Nicholas Marriott
b7397bf413 utf8 option is gone. 2015-11-13 16:05:58 +00:00
Thomas Adam
45a10dde95 Merge branch 'obsd-master' 2015-11-13 14:01:10 +00:00
nicm
88aa1c8dc3 Two spacing and spelling nits. 2015-11-13 12:18:52 +00:00
Thomas Adam
e2917b2627 Merge branch 'obsd-master' 2015-11-13 10:43:07 +00:00
Thomas Adam
3df4959f51 Merge branch 'obsd-master'
Conflicts:
	Makefile
2015-11-13 10:42:45 +00:00
nicm
531869bd92 Add window_visible_layout which ignores zoomed panes and use it for
control mode (which needs to know all panes), from George Nachman.
2015-11-13 10:00:26 +00:00
nicm
c5689a5a40 Long overdue change to the way we store cells in the grid: now, instead
of storing a full grid_cell with UTF-8 data and everything, store a new
type grid_cell_entry. This can either be the cell itself (for ASCII
cells), or an offset into an extended array (per line) for UTF-8
data.

This avoid a large (8 byte) overhead on non-UTF-8 cells (by far the
majority for most users) without the complexity of the shadow array we
had before. Grid memory without any UTF-8 is about half.

The disadvantage that cells can no longer be modified in place and need
to be copied out of the grid and back but it turned out to be lot less
complicated than I expected.
2015-11-13 08:09:28 +00:00
Thomas Adam
a7027ed8e5 Merge branch 'obsd-master' 2015-11-13 00:01:15 +00:00
nicm
e71a915412 Rename overly-long utf8data to ud throughout. 2015-11-12 22:04:37 +00:00
Thomas Adam
b2f19c9d06 Merge branch 'obsd-master' 2015-11-12 16:01:09 +00:00
nicm
f2d03f4fdd grid_put_utf8 is unused, remove it. 2015-11-12 14:50:57 +00:00
Thomas Adam
4f88344df3 Merge branch 'obsd-master' 2015-11-12 14:01:14 +00:00
nicm
a209ea3953 Add utf8_padcstr and use it to align columns in list-keys. 2015-11-12 12:43:36 +00:00
jmc
1da7475d0e tweak previous; ok nicm 2015-11-12 12:36:34 +00:00
nicm
d6daf37df4 Tidy utf8.c a little: build table on first use, and make utf8_width take
a u_int rather than splitting and then combining again in utf8_split.
2015-11-12 12:19:57 +00:00
Thomas Adam
5f483499f3 Merge branch 'obsd-master' 2015-11-12 12:01:17 +00:00
nicm
0cc812ae34 tmux is UTF-8, so if $TMUX is set (tmux running in tmux), the client is
UTF-8. Also try to make the existing checks more readable.
2015-11-12 11:24:08 +00:00
nicm
c41673f3fa If we know the terminal outside tmux is not UTF-8, replace UTF-8 in
error messages and whatnot with underscores the same as we do when we
draw UTF-8 characters as part of the screen.
2015-11-12 11:10:50 +00:00
nicm
1b86f520ea Nuke the utf8 and status-utf8 options and make tmux only a UTF-8
terminal. We still support non-UTF-8 terminals outside tmux, but inside
it is always UTF-8 (as when the utf8 and status-utf8 options were on).
2015-11-12 11:09:11 +00:00
nicm
a0f3999ce7 Remove the mouse_utf8_flag format as well. 2015-11-12 11:07:10 +00:00
nicm
69e0b8326a Support UTF-8 key bindings by expanding the key type from int to
uint64_t and converting UTF-8 to Unicode on input and the reverse on
output. (This allows key bindings, there are still omissions - the
largest being that the various prompts do not accept UTF-8.)
2015-11-12 11:05:34 +00:00
Thomas Adam
333da3b64b Merge branch 'obsd-master' 2015-11-12 10:01:09 +00:00
nicm
7062b0e65d Default history-file should be "" not NULL, from Greg Onufe. 2015-11-12 08:19:18 +00:00
Thomas Adam
f2e4aa8d1c Merge branch 'obsd-master' 2015-11-12 00:01:10 +00:00
nicm
00c34df186 Drop mouse-utf8 option and always turn on UTF-8 mouse if the client says
it supports UTF-8.
2015-11-11 23:23:33 +00:00
Thomas Adam
35fd6d134a Merge branch 'obsd-master'
Conflicts:
	utf8.c
2015-11-11 08:14:36 +00:00
nicm
6f3475c6c7 If realpath() fails just try the original path. 2015-11-10 22:33:47 +00:00
nicm
005e462e01 Handle absolute paths properly, and don't use resolved path in
realpath() fails.
2015-11-10 22:29:33 +00:00
nicm
dcdccf8333 Same bug as last commit, but in the other copy of the loop in this file... 2015-11-05 23:32:21 +00:00
schwarze
e9b58d9de4 Update the internal wcwidth(3) table of tmux(1) to match the data
in /usr/src/share/locale/ctype/en_US.UTF-8.src, with one single
exception:  Keep U+00AD SOFT HYPHEN at width 1 rather than moving
it to width 0, a tradition already observed in the old
https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c .
While here, manually rebalance the btree for optimal lookup speed.
OK nicm@
2015-11-05 16:44:25 +00:00
Thomas Adam
896581628d Merge branch 'obsd-master' 2015-11-05 12:01:08 +00:00
nicm
5577535891 Pass through right click if mouse is on, from Patrick Palka. 2015-11-05 11:05:30 +00:00
Thomas Adam
696826913c Merge branch 'obsd-master' 2015-11-03 16:01:11 +00:00
nicm
455284f1c0 Detach the client we are looping over, from Thomas Adam. 2015-11-03 15:07:36 +00:00
Thomas Adam
c975de2e07 Merge branch 'obsd-master'
Conflicts:
	server.c
2015-10-31 23:56:35 +00:00
nicm
ba7fb49fb9 Fall back silently to ~ or / rather than checking -c with access(), this
was the old behaviour.
2015-10-31 14:51:15 +00:00
nicm
b0a99e85b6 Don't shift version out of peerid, it is needed later. 2015-10-31 13:43:38 +00:00
nicm
abb4e9e2fa The output log is only useful once and it means creating a file, so open
it once at startup instead of in every call to tty_open.
2015-10-31 13:12:03 +00:00
Thomas Adam
17f6c3be8e Merge branch 'obsd-master' 2015-10-31 10:01:12 +00:00
nicm
01defc9f49 Because pledge(2) does not allow us to pass directory file descriptors
around, we can't use file descriptors for the working directory because
we will be unable to pass it to a privileged process to tell it where to
read or write files or spawn children. So move tmux back to using
strings for the current working directory. We try to check it exists
with access() when it is set but ultimately fall back to ~ if it fails
at time of use (or / if that fails too).
2015-10-31 08:13:58 +00:00
Thomas Adam
e8bb385d6d Merge branch 'obsd-master' 2015-10-29 10:01:09 +00:00
nicm
45f3cea263 Break version check into a separate function, and limit version to 8 bits. 2015-10-29 09:35:31 +00:00
Thomas Adam
a5e4d3a2d8 Merge branch 'obsd-master' 2015-10-28 12:01:11 +00:00
nicm
bf9c933cae Like options, move the environ struct into environ.c. 2015-10-28 09:51:55 +00:00
Thomas Adam
da1f6fc2c8 Merge branch 'obsd-master'
Conflicts:
	Makefile
	client.c
	server-client.c
	server.c
	tmux.c
	tmux.h
2015-10-27 23:27:26 +00:00
nicm
44657bf932 Move struct options into options.c. 2015-10-27 15:58:42 +00:00
nicm
67c3a014b9 No more TMPDIR. 2015-10-27 14:51:35 +00:00
nicm
07b0ea03c3 Break the common process set up, event loop and imsg dispatch code
between server and client out into a separate internal API. This will
make it easier to add another process.
2015-10-27 13:23:24 +00:00
Thomas Adam
147b5ae514 Merge branch 'obsd-master' 2015-10-27 10:01:13 +00:00
nicm
9952201ca7 Count brackets in #{?...} so that nested conditional formats work, from
Daniel De Graaf.
2015-10-27 09:28:31 +00:00
nicm
17c2c4219d The format callback may not always succeed, so we need to check for
NULL. From Patrick Palka.
2015-10-27 09:18:06 +00:00
nicm
3fc001d0a2 Use copy-mode -et= in WheelUpPane binding, from Patrick Palka. 2015-10-27 09:15:21 +00:00
Thomas Adam
9c69a79f9a Merge branch 'obsd-master' 2015-10-27 00:01:09 +00:00
nicm
640c6fdd5f If a mouse event has no key binding, pass it through to the pane it
happened in, not the active pane like normal key presses. Fixes problems
seen by Enrico Ghirardi.
2015-10-26 23:16:18 +00:00
nicm
380a1ea8ef Default bindings for mouse wheel on status line to change window (like
we had before), from Patrick Palka.
2015-10-26 23:06:18 +00:00
nicm
b85be36d1c Handle unknown keys more gracefully, return a string instead of NULL. 2015-10-26 22:03:04 +00:00
Thomas Adam
54a3ed751e Merge branch 'obsd-master' 2015-10-26 18:01:12 +00:00
nicm
a22fe33aa0 Some extra logging of where keys are actually going. 2015-10-26 17:17:06 +00:00
Thomas Adam
e95df0bc39 Merge branch 'obsd-master' 2015-10-26 02:01:09 +00:00
jmc
c582f7d177 space before punctuation; 2015-10-26 00:15:37 +00:00
Thomas Adam
ca29903c82 Merge branch 'obsd-master' 2015-10-26 00:01:10 +00:00
nicm
e65306d8e7 Extend the modifiers allowed before formats: as well as the existing
#{=10:...}  length limit, add #{t:...} to convert a time_t format to a
string, #{b:...} for basename and #{d:...} for dirname. Remove all the
foo_string time formats as they can now be replaced by "t:", for example
#{window_activity_string} becomes #{t:window_activity}.
2015-10-25 22:29:17 +00:00
Nicholas Marriott
c14fb5b633 -sys/types.h 2015-10-25 09:38:08 +00:00
Thomas Adam
ad437f13d5 Add missing headers for getpid() 2015-10-25 09:34:56 +00:00
Thomas Adam
4681415a15 Merge branch 'master' of github.com:tmux/tmux 2015-10-25 09:33:11 +00:00
Nicholas Marriott
7930cb54c0 ifdef __OpenBSD__ around pledge(). 2015-10-25 09:31:46 +00:00
Thomas Adam
91f53d590b __OpenBSD__ around pledge() 2015-10-25 09:31:07 +00:00
Thomas Adam
3e0d31c4e9 Merge branch 'obsd-master' 2015-10-25 09:22:20 +00:00
Thomas Adam
4acc8d0ff5 Merge branch 'obsd-master'
Conflicts:
	cmd-find.c
2015-10-25 09:21:37 +00:00
nicm
3faa51a0ca Pass output from jobs through format_expand() so they are expanded again
(this was the previous behaviour).
2015-10-25 08:59:26 +00:00
deraadt
3034a71488 Let's see if anyone screams about not being able to specify $TMPDIR
for their tmux sockets.

(Over the years, I have seen $TMPDIR set up worse than /tmp many times,
and don't know how this practice infected other parts of the system.
Nothing uses tmpdir(3), nor a huge-temporary-file program like sort.)
ok nicm
2015-10-25 07:48:16 +00:00
nicm
2e2b8a95bd Pasting mouse escape sequences is unlikely, so skip them when working
out whether the user is pasting.
2015-10-23 23:46:36 +00:00
nicm
26a55ddcf9 Remove some unnecessary checks before free(). 2015-10-23 16:30:15 +00:00
nicm
1a4ddfa8a7 If $TMUX is set, and we are unsure about the session, use it. 2015-10-23 16:29:07 +00:00
nicm
5383b047d1 tmux can call pledge() in main with large set and then reduce it
slightly in the server to "stdio rpath wpath cpath fattr unix recvfd
proc exec tty ps".
2015-10-23 16:07:29 +00:00
nicm
14da999408 Format for scroll position, from Jorge Morante. 2015-10-23 16:02:21 +00:00
nicm
63a3fd3c0f Use tty_term_flag not _has for XT, and make -2 force direct use of
256-colour escape sequences (so setaf/setab can be bypassed if needed).
2015-10-23 15:52:54 +00:00
Thomas Adam
8c39813665 Merge branch 'obsd-master' 2015-10-22 14:01:12 +01:00
nicm
3ebcf25149 If the pane is still on all_window_panes but not actually connected to
window or session (which can happen if it is killed during a command
sequence and something else has a reference), fall back to the best
effort. Fixes "tmux killw\; detach" for Rudis Muiznieks.
2015-10-22 11:23:00 +00:00
nicm
a05c27a7e1 Unzoom before -LRUD, reported by Andy Weidenbaum. 2015-10-22 11:19:31 +00:00
Thomas Adam
6bc3902f5d Merge branch 'obsd-master' 2015-10-22 12:01:09 +01:00
nicm
c2c2d44c72 Log identify messages. 2015-10-22 11:00:51 +00:00
nicm
515dfea4b7 This should not be changed. 2015-10-22 10:48:30 +00:00
nicm
31fd071faa Rename shutdown to exit. 2015-10-22 10:46:24 +00:00
Thomas Adam
0bfa615997 Merge branch 'obsd-master' 2015-10-21 16:01:08 +01:00
nicm
60ca29df64 client_key_table was missing. 2015-10-21 13:14:36 +00:00
Thomas Adam
35f582583a Merge branch 'obsd-master' 2015-10-21 14:01:09 +01:00
nicm
ddbc4a0f6c By popular demand add a default binding for mouse wheel up to scroll
into history (if the mouse is, on of course).
2015-10-21 11:13:47 +00:00
Thomas Adam
1f4a5b5dfe Merge branch 'obsd-master' 2015-10-21 00:01:19 +01:00
nicm
076034345a Use client pointer not file descriptor in logging. 2015-10-20 21:12:08 +00:00
Thomas Adam
af2d48f4d2 Merge branch 'obsd-master' 2015-10-20 16:01:11 +01:00
nicm
8c8cddbe02 The table could change when retrying so don't save it at start of
server_client_handle_key.
2015-10-20 14:19:27 +00:00
Thomas Adam
bbdc08780c Merge branch 'obsd-master' 2015-10-18 22:01:08 +01:00
nicm
174a2ad731 Pass current directory as a string rather than a file descriptor because
pledge doesn't let us pass directory file descriptors.
2015-10-18 20:42:42 +00:00
Thomas Adam
7c78b2b756 Start working on tmux 2.2 2015-10-18 18:19:08 +01:00
158 changed files with 6650 additions and 5645 deletions

View File

@@ -1,9 +1,9 @@
Bob Beck <beck@openbsd.org> beck <beck>
Claudio Jeker <claudio@openbsd.org> claudio <claudio>
Igor Sobrado <sobrado@openbsd.org> sobrado <sobrado>
Ingo Schwarze <schwarze@openbsd.org> schwarze <schwarze>
Jacek Masiulaniec <jacekm@openbsd.org> jacekm <jacekm>
Jason McIntyre <jmc@openbsd.org> jmc <jmc>
Jason McIntyre <jmc@openbsd.org> jcm <jcm>
Joel Sing <jsing@openbsd.org> jsing <jsing>
Jonathan Gray <jsg@openbsd.org> jsg <jsg>
Kenneth R Westerback <krw@openbsd.org> krw <krw>
@@ -11,6 +11,7 @@ Marc Espie <espie@openbsd.org> espie <espie>
Matthew Dempsky <matthew@openbsd.org> matthew <matthew>
Matthias Kilian <kili@openbsd.org> kili <kili>
Matthieu Herrb <matthieu@openbsd.org> matthieu <matthieu>
Michael McConville <mmcc@openbsd.org> mmcc <mmcc>
Miod Vallat <miod@openbsd.org> miod <miod>
Nicholas Marriott <nicholas.marriott@gmail.com> Nicholas Marriott <nicm@openbsd.org>
Nicholas Marriott <nicholas.marriott@gmail.com> nicm <nicm>
@@ -24,11 +25,12 @@ Sebastian Benoit <benno@openbsd.org> benno <benno>
Stefan Sperling <stsp@openbsd.org> stsp <stsp>
Stuart Henderson <sthen@openbsd.org> sthen <sthen>
Ted Unangst <tedu@openbsd.org> tedu <tedu>
Theo de Raadt <deraadt@openbsd.org> deraadt <deraadt>
Theo de Raadt <deraadt@openbsd.org> Theo Deraadt <deraadt@openbsd.org>
Theo de Raadt <deraadt@openbsd.org> deraadt <deraadt>
Thomas Adam <thomas@xteddy.org> Thomas <thomas@xteddy.org>
Thomas Adam <thomas@xteddy.org> n6tadam <n6tadam@xteddy.org>
Thomas Adam <thomas@xteddy.org> Thomas Adam <thomas.adam@smoothwall.net>
Thomas Adam <thomas@xteddy.org> n6tadam <n6tadam@xteddy.org>
Tim van der Molen <tim@openbsd.org> tim <tim>
Tobias Stoeckmann <tobias@openbsd.org> tobias <tobias>
Todd C Miller <millert@openbsd.org> millert <millert>
William Yodlowsky <william@openbsd.org> william <william>

66
CHANGES
View File

@@ -1,3 +1,69 @@
CHANGES FROM 2.1 to 2.2 10 April 2016
Incompatible Changes
====================
* The format strings which referenced time have been removed. Instead:
#{t:window_activity}
can be used.
* Support for TMPDIR has been removed. Use TMUX_TMPDIR instead.
* UTF8 detection how happens automatically if the client supports it, hence
the:
mouse-utf8
utf8
options has been removed.
* The:
mouse_utf8_flag
format string has been removed.
* The -I option to show-messages has been removed. See:
#{t:start_time}
format option instead.
Normal Changes
==============
* Panes are unzoomed with selectp -LRUD
* New formats added:
#{scroll_position}
#{socket_path}
#{=10:...} -- limit to N characters (from the start)
#{=-10:...} -- limit to N characters (from the end)
#{t:...} -- used to format time-based formats
#{b:...} -- used to ascertain basename from string
#{d:...} -- used to ascertain dirname from string
#{s:...} -- used to perform substitutions on a string
* Job output is run via the format system, so formats work again
* If display-time is set to 0, then the indicators wait for a key to be
pressed.
* list-keys and list-commands can be run without starting the tmux server.
* kill-session learns -C to clear all alerts in all windows of the session.
* Support for hooks (internal for now), but hooks for the following have been
implemented:
alert-bell
alert-silence
alert-activity
client-attached
client-detached
client-resized
pane-died
pane-exited
* RGB (24bit) colour support. The 'Tc' flag must be set in the external TERM
entry (using terminal-overrides or a custom terminfo entry).
CHANGES FROM 2.0 to 2.1 18 October 2015
Incompatible Changes

View File

@@ -6,8 +6,8 @@ CLEANFILES = tmux.1.mdoc tmux.1.man
# Distribution tarball options.
EXTRA_DIST = \
CHANGES FAQ README TODO COPYING examples compat/*.[ch] \
array.h compat.h tmux.h osdep-*.c mdoc2man.awk tmux.1
CHANGES FAQ README TODO COPYING example_tmux.conf compat/*.[ch] \
array.h compat.h tmux.h osdep-*.c xmalloc.h mdoc2man.awk tmux.1
dist-hook:
make clean
grep "^#found_debug=" configure
@@ -30,7 +30,7 @@ CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign
CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
CPPFLAGS += -DDEBUG
endif
if IS_COVERAGE
@@ -54,7 +54,7 @@ if IS_SUNCC
CFLAGS += -erroff=E_EMPTY_DECLARATION
endif
# Set _LINUX_SOURCE_COMPAT for AIX for mallocing 0 bytes
# Set _LINUX_SOURCE_COMPAT for AIX for malloc(0).
if IS_AIX
DEFS += -D_LINUX_SOURCE_COMPAT=1
endif
@@ -118,6 +118,7 @@ dist_tmux_SOURCES = \
cmd-send-keys.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-hook.c \
cmd-set-option.c \
cmd-show-environment.c \
cmd-show-messages.c \
@@ -136,9 +137,9 @@ dist_tmux_SOURCES = \
control-notify.c \
environ.c \
format.c \
grid-cell.c \
grid-view.c \
grid.c \
hooks.c \
input-keys.c \
input.c \
job.c \
@@ -154,6 +155,7 @@ dist_tmux_SOURCES = \
options-table.c \
options.c \
paste.c \
proc.c \
resize.c \
screen-redraw.c \
screen-write.c \
@@ -234,6 +236,9 @@ endif
if NO_OPENAT
nodist_tmux_SOURCES += compat/openat.c
endif
if NO_REALLOCARRAY
nodist_tmux_SOURCES += compat/reallocarray.c
endif
# Install tmux.1 in the right format.
install-exec-hook:

24
README
View File

@@ -8,13 +8,16 @@ This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
tmux depends on libevent 2.x. Download it from:
http://www.monkey.org/~provos/libevent/
http://libevent.org
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
By default, tmux will use the utempter library to update utmp(5), if it is
installed. Run configure with --disable-utempter to disable this.
To get and build the latest from version control:
$ git clone https://github.com/tmux/tmux.git
@@ -33,8 +36,16 @@ the source tree with:
Some common questions are answered in the FAQ file and a more extensive (but
slightly out of date) guide is available in the OpenBSD FAQ at
http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
file and some example configurations and a Vim syntax file are in the examples
directory.
file and an example configuration in example_tmux.conf.
A vim(1) syntax file is available at:
https://github.com/keith/tmux.vim
https://raw.githubusercontent.com/keith/tmux.vim/master/syntax/tmux.vim
And a bash(1) completion file at:
https://github.com/przepompownia/tmux-bash-completion
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
@@ -52,10 +63,7 @@ welcome. Please send by email to:
tmux-users@googlegroups.com
This file and the CHANGES, FAQ, SYNCING and TODO files are licensed under
the ISC license. Files under examples/ remain copyright their authors unless
otherwise stated in the file but permission has been received to distribute
them with tmux. All other files have a license and copyright notice at their
start.
This file and the CHANGES, FAQ, SYNCING and TODO files are licensed under the
ISC license. All other files have a license and copyright notice at their start.
-- Nicholas Marriott <nicholas.marriott@gmail.com>

23
TODO
View File

@@ -5,6 +5,8 @@
* ' and " should be parsed the same (eg "\e" vs '\e') in config
and command prompt
* last-pane across sessions
* list-keys should quote output so that bindings can just be used in
config file as-is
- make command sequences more usable
* don't require space after ;
@@ -15,10 +17,9 @@
* way to set socket path from config file
- format improvements:
* option to quote format (#{session_name:quoted})
* option to quote format (#{q:session_name})
* formats need conditions for >0 (for #P)
* some way to pad # stuff with spaces
* last window update time and format for it
* formats to show if a window is linked into multiple sessions, into
multiple attached sessions, and is the active window in multiple
attached sessions?
@@ -51,10 +52,8 @@
* split-window -> split-pane?
- better UTF-8 support:
* window names and titles
* message display
* prompt input
* multibyte key input
* searching in copy mode
- copy/paste improvements:
@@ -63,6 +62,20 @@
* command to toggle selection not to move it in copy-mode
* regex searching
* copy-pipe should have -x as well
* copy mode key bindings should just be a standard key table, using
something like "copy-mode start-selection"; it could use
command-prompt for search, goto, etc:
bind -Temacs command-prompt -p'Search Up: ' 'copy-mode search-up %%'
it'd need a separate lookup, because modes are per-pane, perhaps a
table() cb to give the table name ("vi" or "emacs"). anything in the
table fires the command, anything not in the table is injected as a
key
* searching in copy mode should unwrap lines, so if you seach for "foobar"
then it should be found even if it is now "foo\nbar" (if the WRAP flag
is set on the line)
* {} to go to next/previous blank line in copy mode
- layout stuff
* way to tag a layout as a number/name
@@ -119,7 +132,7 @@
comes from config for new sessions and windows. likewise, panes and
jobs and run-shell and lock command all start with slightly different
environments
* multiline status line?
* multiline status line? separate command prompt and status line?
* customizable command aliases
* automatic pane logging
* BCE? We are halfway there (output side is done for pane backgrounds),

117
alerts.c
View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,13 +29,15 @@ int alerts_enabled(struct window *, int);
void alerts_callback(int, short, void *);
void alerts_reset(struct window *);
void alerts_run_hook(struct session *, struct winlink *, int);
int alerts_check_all(struct session *, struct winlink *);
int alerts_check_bell(struct session *, struct winlink *);
int alerts_check_activity(struct session *, struct winlink *);
int alerts_check_silence(struct session *, struct winlink *);
void alerts_ring_bell(struct session *);
void
alerts_timer(unused int fd, unused short events, void *arg)
alerts_timer(__unused int fd, __unused short events, void *arg)
{
struct window *w = arg;
@@ -45,7 +47,7 @@ alerts_timer(unused int fd, unused short events, void *arg)
}
void
alerts_callback(unused int fd, unused short events, unused void *arg)
alerts_callback(__unused int fd, __unused short events, __unused void *arg)
{
struct window *w;
struct session *s;
@@ -59,11 +61,7 @@ alerts_callback(unused int fd, unused short events, unused void *arg)
continue;
flags = w->flags;
alerts = alerts_check_bell(s, wl);
alerts |= alerts_check_activity(s, wl);
alerts |= alerts_check_silence(s, wl);
if (alerts != 0)
server_status_session(s);
alerts = alerts_check_all(s, wl);
log_debug("%s:%d @%u alerts check, alerts %#x, "
"flags %#x", s->name, wl->idx, w->id,
@@ -74,25 +72,58 @@ alerts_callback(unused int fd, unused short events, unused void *arg)
alerts_fired = 0;
}
void
alerts_run_hook(struct session *s, struct winlink *wl, int flags)
{
struct cmd_find_state fs;
if (cmd_find_from_winlink(&fs, s, wl) != 0)
return;
if (flags & WINDOW_BELL)
hooks_run(s->hooks, NULL, &fs, "alert-bell");
if (flags & WINDOW_SILENCE)
hooks_run(s->hooks, NULL, &fs, "alert-silence");
if (flags & WINDOW_ACTIVITY)
hooks_run(s->hooks, NULL, &fs, "alert-activity");
}
int
alerts_check_all(struct session *s, struct winlink *wl)
{
int alerts;
alerts = alerts_check_bell(s, wl);
alerts |= alerts_check_activity(s, wl);
alerts |= alerts_check_silence(s, wl);
if (alerts != 0) {
alerts_run_hook(s, wl, alerts);
server_status_session(s);
}
return (alerts);
}
void
alerts_check_session(struct session *s)
{
struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows)
alerts_check_all(s, wl);
}
int
alerts_enabled(struct window *w, int flags)
{
struct session *s;
if (flags & WINDOW_BELL)
return (1);
if (flags & WINDOW_ACTIVITY) {
if (options_get_number(&w->options, "monitor-activity"))
if (options_get_number(w->options, "monitor-activity"))
return (1);
}
if (flags & WINDOW_SILENCE) {
if (options_get_number(&w->options, "monitor-silence") != 0)
return (1);
}
if (~flags & WINDOW_BELL)
return (0);
RB_FOREACH(s, sessions, &sessions) {
if (!session_has(s, w))
continue;
if (options_get_number(&s->options, "bell-action") != BELL_NONE)
if (options_get_number(w->options, "monitor-silence") != 0)
return (1);
}
return (0);
@@ -116,7 +147,7 @@ alerts_reset(struct window *w)
event_del(&w->alerts_timer);
timerclear(&tv);
tv.tv_sec = options_get_number(&w->options, "monitor-silence");
tv.tv_sec = options_get_number(w->options, "monitor-silence");
log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
if (tv.tv_sec != 0)
@@ -132,15 +163,15 @@ alerts_queue(struct window *w, int flags)
if (!event_initialized(&w->alerts_timer))
evtimer_set(&w->alerts_timer, alerts_timer, w);
if (w->flags & flags)
return;
w->flags |= flags;
log_debug("@%u alerts flags added %#x", w->id, flags);
if (!alerts_fired) {
w->flags |= flags;
log_debug("@%u alerts flags added %#x", w->id, flags);
if (!alerts_fired && alerts_enabled(w, flags)) {
log_debug("alerts check queued (by @%u)", w->id);
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
alerts_fired = 1;
if (alerts_enabled(w, flags)) {
log_debug("alerts check queued (by @%u)", w->id);
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
alerts_fired = 1;
}
}
}
@@ -151,20 +182,20 @@ alerts_check_bell(struct session *s, struct winlink *wl)
struct window *w = wl->window;
int action, visual;
if (!(w->flags & WINDOW_BELL) || wl->flags & WINLINK_BELL)
if (!(w->flags & WINDOW_BELL))
return (0);
if (s->curw != wl || s->flags & SESSION_UNATTACHED)
if (s->curw != wl) {
wl->flags |= WINLINK_BELL;
if (s->flags & SESSION_UNATTACHED)
return (0);
w->flags &= ~WINDOW_BELL;
}
if (s->curw->window == w)
w->flags &= ~WINDOW_BELL;
action = options_get_number(&s->options, "bell-action");
action = options_get_number(s->options, "bell-action");
if (action == BELL_NONE)
return (0);
visual = options_get_number(&s->options, "visual-bell");
visual = options_get_number(s->options, "visual-bell");
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s || c->flags & CLIENT_CONTROL)
continue;
@@ -198,17 +229,17 @@ alerts_check_activity(struct session *s, struct winlink *wl)
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
return (0);
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
if (s->curw == wl)
return (0);
if (!options_get_number(&w->options, "monitor-activity"))
if (!options_get_number(w->options, "monitor-activity"))
return (0);
if (options_get_number(&s->options, "bell-on-alert"))
if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s);
wl->flags |= WINLINK_ACTIVITY;
if (options_get_number(&s->options, "visual-activity")) {
if (options_get_number(s->options, "visual-activity")) {
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s)
continue;
@@ -230,17 +261,17 @@ alerts_check_silence(struct session *s, struct winlink *wl)
if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
return (0);
if (s->curw == wl && !(s->flags & SESSION_UNATTACHED))
if (s->curw == wl)
return (0);
if (options_get_number(&w->options, "monitor-silence") == 0)
if (options_get_number(w->options, "monitor-silence") == 0)
return (0);
if (options_get_number(&s->options, "bell-on-alert"))
if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s);
wl->flags |= WINLINK_SILENCE;
if (options_get_number(&s->options, "visual-silence")) {
if (options_get_number(s->options, "visual-silence")) {
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s)
continue;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -127,77 +127,73 @@ args_free(struct args *args)
free(args);
}
/* Print a set of arguments. */
size_t
args_print(struct args *args, char *buf, size_t len)
/* Add to string. */
static void printflike(3, 4)
args_print_add(char **buf, size_t *len, const char *fmt, ...)
{
size_t off, used;
va_list ap;
char *s;
size_t slen;
va_start(ap, fmt);
slen = xvasprintf(&s, fmt, ap);
va_end(ap);
*len += slen;
*buf = xrealloc(*buf, *len);
strlcat(*buf, s, *len);
free(s);
}
/* Print a set of arguments. */
char *
args_print(struct args *args)
{
size_t len;
char *buf;
int i;
const char *quotes;
struct args_entry *entry;
/* There must be at least one byte at the start. */
if (len == 0)
return (0);
off = 0;
len = 1;
buf = xcalloc(1, len);
/* Process the flags first. */
buf[off++] = '-';
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->value != NULL)
continue;
if (off == len - 1) {
buf[off] = '\0';
return (len);
}
buf[off++] = entry->flag;
buf[off] = '\0';
if (*buf == '\0')
args_print_add(&buf, &len, "-");
args_print_add(&buf, &len, "%c", entry->flag);
}
if (off == 1)
buf[--off] = '\0';
/* Then the flags with arguments. */
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->value == NULL)
continue;
if (off >= len) {
/* snprintf will have zero terminated. */
return (len);
}
if (strchr(entry->value, ' ') != NULL)
quotes = "\"";
if (*buf != '\0')
args_print_add(&buf, &len, " -%c ", entry->flag);
else
quotes = "";
used = xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
off != 0 ? " " : "", entry->flag, quotes, entry->value,
quotes);
if (used > len - off)
used = len - off;
off += used;
args_print_add(&buf, &len, "-%c ", entry->flag);
if (strchr(entry->value, ' ') != NULL)
args_print_add(&buf, &len, "\"%s\"", entry->value);
else
args_print_add(&buf, &len, "%s", entry->value);
}
/* And finally the argument vector. */
for (i = 0; i < args->argc; i++) {
if (off >= len) {
/* snprintf will have zero terminated. */
return (len);
}
if (*buf != '\0')
args_print_add(&buf, &len, " ");
if (strchr(args->argv[i], ' ') != NULL)
quotes = "\"";
args_print_add(&buf, &len, "\"%s\"", args->argv[i]);
else
quotes = "";
used = xsnprintf(buf + off, len - off, "%s%s%s%s",
off != 0 ? " " : "", quotes, args->argv[i], quotes);
if (used > len - off)
used = len - off;
off += used;
args_print_add(&buf, &len, "%s", args->argv[i]);
}
return (off);
return (buf);
}
/* Return if an argument is present. */

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2006 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

4
cfg.c
View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -132,7 +132,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
}
void
cfg_default_done(unused struct cmd_q *cmdq)
cfg_default_done(__unused struct cmd_q *cmdq)
{
if (--cfg_references != 0)
return;

609
client.c
View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,10 +33,10 @@
#include "tmux.h"
int client_flags;
struct imsgbuf client_ibuf;
struct event client_event;
struct event client_stdin;
struct tmuxproc *client_proc;
struct tmuxpeer *client_peer;
int client_flags;
struct event client_stdin;
enum {
CLIENT_EXIT_NONE,
CLIENT_EXIT_DETACHED,
@@ -47,41 +47,40 @@ enum {
CLIENT_EXIT_EXITED,
CLIENT_EXIT_SERVER_EXITED,
} client_exitreason = CLIENT_EXIT_NONE;
int client_exitval;
enum msgtype client_exittype;
const char *client_exitsession;
int client_attached;
int client_exitval;
enum msgtype client_exittype;
const char *client_exitsession;
int client_attached;
__dead void client_exec(const char *);
__dead void client_exec(const char *,const char *);
int client_get_lock(char *);
int client_connect(struct event_base *, char *, int);
void client_send_identify(const char *, int);
int client_write_one(enum msgtype, int, const void *, size_t);
int client_write_server(enum msgtype, const void *, size_t);
void client_update_event(void);
void client_signal(int, short, void *);
int client_connect(struct event_base *, const char *, int);
void client_send_identify(const char *, const char *);
void client_stdin_callback(int, short, void *);
void client_write(int, const char *, size_t);
void client_callback(int, short, void *);
int client_dispatch_attached(void);
int client_dispatch_wait(void);
void client_signal(int);
void client_dispatch(struct imsg *, void *);
void client_dispatch_attached(struct imsg *);
void client_dispatch_wait(struct imsg *, const char *);
const char *client_exit_message(void);
/*
* Get server create lock. If already held then server start is happening in
* another client, so block until the lock is released and return -1 to
* retry. Ignore other errors - just continue and start the server without the
* lock.
* another client, so block until the lock is released and return -2 to
* retry. Return -1 on failure to continue and start the server anyway.
*/
int
client_get_lock(char *lockfile)
{
int lockfd;
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1)
fatal("open failed");
log_debug("lock file is %s", lockfile);
if ((lockfd = open(lockfile, O_WRONLY|O_CREAT, 0600)) == -1) {
log_debug("open failed: %s", strerror(errno));
return (-1);
}
if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
log_debug("flock failed: %s", strerror(errno));
if (errno != EAGAIN)
@@ -89,7 +88,7 @@ client_get_lock(char *lockfile)
while (flock(lockfd, LOCK_EX) == -1 && errno == EINTR)
/* nothing */;
close(lockfd);
return (-1);
return (-2);
}
log_debug("flock succeeded");
@@ -98,7 +97,7 @@ client_get_lock(char *lockfile)
/* Connect client to server. */
int
client_connect(struct event_base *base, char *path, int start_server)
client_connect(struct event_base *base, const char *path, int start_server)
{
struct sockaddr_un sa;
size_t size;
@@ -116,10 +115,10 @@ client_connect(struct event_base *base, char *path, int start_server)
retry:
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket failed");
return (-1);
log_debug("trying connect");
if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
if (connect(fd, (struct sockaddr *)&sa, sizeof sa) == -1) {
log_debug("connect failed: %s", strerror(errno));
if (errno != ECONNREFUSED && errno != ENOENT)
goto failed;
@@ -129,12 +128,16 @@ retry:
if (!locked) {
xasprintf(&lockfile, "%s.lock", path);
if ((lockfd = client_get_lock(lockfile)) == -1) {
log_debug("didn't get lock");
if ((lockfd = client_get_lock(lockfile)) < 0) {
log_debug("didn't get lock (%d)", lockfd);
free(lockfile);
goto retry;
lockfile = NULL;
if (lockfd == -2)
goto retry;
}
log_debug("got lock");
log_debug("got lock (%d)", lockfd);
/*
* Always retry at least once, even if we got the lock,
@@ -146,7 +149,7 @@ retry:
goto retry;
}
if (unlink(path) != 0 && errno != ENOENT) {
if (lockfd >= 0 && unlink(path) != 0 && errno != ENOENT) {
free(lockfile);
close(lockfd);
return (-1);
@@ -154,7 +157,7 @@ retry:
fd = server_start(base, lockfd, lockfile);
}
if (locked) {
if (locked && lockfd >= 0) {
free(lockfile);
close(lockfd);
}
@@ -209,25 +212,29 @@ client_exit_message(void)
/* Client main loop. */
int
client_main(struct event_base *base, int argc, char **argv, int flags)
client_main(struct event_base *base, int argc, char **argv, int flags,
const char *shellcmd)
{
struct cmd *cmd;
struct cmd_list *cmdlist;
struct msg_command_data *data;
int cmdflags, fd, i, cwd;
const char* ttynam;
int cmdflags, fd, i;
const char *ttynam, *cwd;
pid_t ppid;
enum msgtype msg;
char *cause;
char *cause, path[PATH_MAX];
struct termios tio, saved_tio;
size_t size;
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
signal(SIGCHLD, SIG_IGN);
/* Save the flags. */
client_flags = flags;
/* Set up the initial command. */
cmdflags = 0;
if (shell_cmd != NULL) {
if (shellcmd != NULL) {
msg = MSG_SHELL;
cmdflags = CMD_STARTSERVER;
} else if (argc == 0) {
@@ -254,8 +261,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
cmd_list_free(cmdlist);
}
/* Establish signal handlers. */
set_signals(client_signal);
/* Create client process structure (starts logging). */
client_proc = proc_start("client", base, 0, client_signal);
/* Initialize the client socket and start the server. */
fd = client_connect(base, socket_path, cmdflags & CMD_STARTSERVER);
@@ -269,10 +276,14 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
}
return (1);
}
client_peer = proc_add_peer(client_proc, fd, client_dispatch,
(void *)shellcmd);
/* Save these before pledge(). */
if ((cwd = open(".", O_RDONLY)) == -1)
cwd = open("/", O_RDONLY);
if ((cwd = getcwd(path, sizeof path)) == NULL) {
if ((cwd = find_home()) == NULL)
cwd = "/";
}
if ((ttynam = ttyname(STDIN_FILENO)) == NULL)
ttynam = "";
@@ -291,31 +302,18 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
#endif
/* Free stuff that is not used in the client. */
options_free(&global_options);
options_free(&global_s_options);
options_free(&global_w_options);
environ_free(&global_environ);
/* Set process title, log and signals now this is the client. */
#ifdef HAVE_SETPROCTITLE
setproctitle("client (%s)", socket_path);
#endif
logfile("client");
/* Create imsg. */
imsg_init(&client_ibuf, fd);
event_set(&client_event, fd, EV_READ, client_callback, NULL);
options_free(global_options);
options_free(global_s_options);
options_free(global_w_options);
environ_free(global_environ);
/* Create stdin handler. */
setblocking(STDIN_FILENO, 0);
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
client_stdin_callback, NULL);
if (client_flags & CLIENT_CONTROLCONTROL) {
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
fprintf(stderr, "tcgetattr failed: %s\n",
strerror(errno));
return (1);
}
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0)
fatal("tcgetattr failed");
cfmakeraw(&tio);
tio.c_iflag = ICRNL|IXANY;
tio.c_oflag = OPOST|ONLCR;
@@ -331,7 +329,7 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
}
/* Send identify messages. */
client_send_identify(ttynam, cwd); /* closes cwd */
client_send_identify(ttynam, cwd);
/* Send first command. */
if (msg == MSG_COMMAND) {
@@ -351,18 +349,17 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
size += sizeof *data;
/* Send the command. */
if (client_write_server(msg, data, size) != 0) {
if (proc_send(client_peer, msg, -1, data, size) != 0) {
fprintf(stderr, "failed to send command\n");
free(data);
return (1);
}
free(data);
} else if (msg == MSG_SHELL)
client_write_server(msg, NULL, 0);
proc_send(client_peer, msg, -1, NULL, 0);
/* Set the event and dispatch. */
client_update_event();
event_dispatch();
/* Start main loop. */
proc_loop(client_proc, NULL);
/* Print the exit message, if any, and exit. */
if (client_attached) {
@@ -379,14 +376,15 @@ client_main(struct event_base *base, int argc, char **argv, int flags)
printf("%%exit\n");
printf("\033\\");
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
}
} else if (client_exitreason != CLIENT_EXIT_NONE)
fprintf(stderr, "%s\n", client_exit_message());
setblocking(STDIN_FILENO, 1);
return (client_exitval);
}
/* Send identify messages to server. */
void
client_send_identify(const char *ttynam, int cwd)
client_send_identify(const char *ttynam, const char *cwd)
{
const char *s;
char **ss;
@@ -394,149 +392,37 @@ client_send_identify(const char *ttynam, int cwd)
int fd, flags = client_flags;
pid_t pid;
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
if ((s = getenv("TERM")) == NULL)
s = "";
client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
client_write_one(MSG_IDENTIFY_TTYNAME, -1, ttynam, strlen(ttynam) + 1);
client_write_one(MSG_IDENTIFY_CWD, cwd, NULL, 0);
proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam,
strlen(ttynam) + 1);
proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1);
if ((fd = dup(STDIN_FILENO)) == -1)
fatal("dup failed");
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0);
pid = getpid();
client_write_one(MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
for (ss = environ; *ss != NULL; ss++) {
sslen = strlen(*ss) + 1;
if (sslen <= MAX_IMSGSIZE - IMSG_HEADER_SIZE)
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
if (sslen > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
continue;
proc_send(client_peer, MSG_IDENTIFY_ENVIRON, -1, *ss, sslen);
}
client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0);
}
/* Helper to send one message. */
int
client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
{
int retval;
retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd,
(void *)buf, len);
if (retval != 1)
return (-1);
return (0);
}
/* Write a message to the server without a file descriptor. */
int
client_write_server(enum msgtype type, const void *buf, size_t len)
{
int retval;
retval = client_write_one(type, -1, buf, len);
if (retval == 0)
client_update_event();
return (retval);
}
/* Update client event based on whether it needs to read or read and write. */
void
client_update_event(void)
{
short events;
event_del(&client_event);
events = EV_READ;
if (client_ibuf.w.queued > 0)
events |= EV_WRITE;
event_set(&client_event, client_ibuf.fd, events, client_callback, NULL);
event_add(&client_event, NULL);
}
/* Callback to handle signals in the client. */
void
client_signal(int sig, unused short events, unused void *arg)
{
struct sigaction sigact;
int status;
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGTERM)
event_loopexit(NULL);
} else {
switch (sig) {
case SIGHUP:
client_exitreason = CLIENT_EXIT_LOST_TTY;
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
case SIGTERM:
client_exitreason = CLIENT_EXIT_TERMINATED;
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
case SIGWINCH:
client_write_server(MSG_RESIZE, NULL, 0);
break;
case SIGCONT:
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
client_write_server(MSG_WAKEUP, NULL, 0);
break;
}
}
client_update_event();
}
/* Callback for client imsg read events. */
void
client_callback(unused int fd, short events, unused void *arg)
{
ssize_t n;
int retval;
if (events & EV_READ) {
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
goto lost_server;
if (client_attached)
retval = client_dispatch_attached();
else
retval = client_dispatch_wait();
if (retval != 0) {
event_loopexit(NULL);
return;
}
}
if (events & EV_WRITE) {
if (msgbuf_write(&client_ibuf.w) <= 0 && errno != EAGAIN)
goto lost_server;
}
client_update_event();
return;
lost_server:
client_exitreason = CLIENT_EXIT_LOST_SERVER;
client_exitval = 1;
event_loopexit(NULL);
proc_send(client_peer, MSG_IDENTIFY_DONE, -1, NULL, 0);
}
/* Callback for client stdin read events. */
void
client_stdin_callback(unused int fd, unused short events, unused void *arg)
client_stdin_callback(__unused int fd, __unused short events,
__unused void *arg)
{
struct msg_stdin_data data;
@@ -544,10 +430,9 @@ client_stdin_callback(unused int fd, unused short events, unused void *arg)
if (data.size < 0 && (errno == EINTR || errno == EAGAIN))
return;
client_write_server(MSG_STDIN, &data, sizeof data);
proc_send(client_peer, MSG_STDIN, -1, &data, sizeof data);
if (data.size <= 0)
event_del(&client_stdin);
client_update_event();
}
/* Force write to file descriptor. */
@@ -570,12 +455,12 @@ client_write(int fd, const char *data, size_t size)
/* Run command in shell; used for -c. */
__dead void
client_exec(const char *shell)
client_exec(const char *shell, const char *shellcmd)
{
const char *name, *ptr;
char *argv0;
log_debug("shell %s, command %s", shell, shell_cmd);
log_debug("shell %s, command %s", shell, shellcmd);
ptr = strrchr(shell, '/');
if (ptr != NULL && *(ptr + 1) != '\0')
@@ -593,17 +478,73 @@ client_exec(const char *shell)
setblocking(STDERR_FILENO, 1);
closefrom(STDERR_FILENO + 1);
execl(shell, argv0, "-c", shell_cmd, (char *) NULL);
execl(shell, argv0, "-c", shellcmd, (char *) NULL);
fatal("execl failed");
}
/* Dispatch imsgs when in wait state (before MSG_READY). */
int
client_dispatch_wait(void)
/* Callback to handle signals in the client. */
void
client_signal(int sig)
{
struct sigaction sigact;
int status;
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGTERM)
proc_exit(client_proc);
} else {
switch (sig) {
case SIGHUP:
client_exitreason = CLIENT_EXIT_LOST_TTY;
client_exitval = 1;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case SIGTERM:
client_exitreason = CLIENT_EXIT_TERMINATED;
client_exitval = 1;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case SIGWINCH:
proc_send(client_peer, MSG_RESIZE, -1, NULL, 0);
break;
case SIGCONT:
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
proc_send(client_peer, MSG_WAKEUP, -1, NULL, 0);
break;
}
}
}
/* Callback for client read events. */
void
client_dispatch(struct imsg *imsg, void *arg)
{
if (imsg == NULL) {
client_exitreason = CLIENT_EXIT_LOST_SERVER;
client_exitval = 1;
proc_exit(client_proc);
return;
}
if (client_attached)
client_dispatch_attached(imsg);
else
client_dispatch_wait(imsg, arg);
}
/* Dispatch imsgs when in wait state (before MSG_READY). */
void
client_dispatch_wait(struct imsg *imsg, const char *shellcmd)
{
struct imsg imsg;
char *data;
ssize_t n, datalen;
ssize_t datalen;
struct msg_stdout_data stdoutdata;
struct msg_stderr_data stderrdata;
int retval;
@@ -623,163 +564,141 @@ client_dispatch_wait(void)
};
#endif
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
data = imsg->data;
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
log_debug("got %u from server", imsg.hdr.type);
switch (imsg.hdr.type) {
case MSG_EXIT:
case MSG_SHUTDOWN:
if (datalen != sizeof retval && datalen != 0)
fatalx("bad MSG_EXIT size");
if (datalen == sizeof retval) {
memcpy(&retval, data, sizeof retval);
client_exitval = retval;
}
imsg_free(&imsg);
return (-1);
case MSG_READY:
if (datalen != 0)
fatalx("bad MSG_READY size");
event_del(&client_stdin);
client_attached = 1;
client_write_server(MSG_RESIZE, NULL, 0);
break;
case MSG_STDIN:
if (datalen != 0)
fatalx("bad MSG_STDIN size");
event_add(&client_stdin, NULL);
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
fatalx("bad MSG_STDOUT size");
memcpy(&stdoutdata, data, sizeof stdoutdata);
client_write(STDOUT_FILENO, stdoutdata.data,
stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
fatalx("bad MSG_STDERR size");
memcpy(&stderrdata, data, sizeof stderrdata);
client_write(STDERR_FILENO, stderrdata.data,
stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
fatalx("bad MSG_VERSION size");
fprintf(stderr, "protocol version mismatch "
"(client %d, server %u)\n", PROTOCOL_VERSION,
imsg.hdr.peerid);
client_exitval = 1;
imsg_free(&imsg);
return (-1);
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_SHELL string");
clear_signals(0);
client_exec(data);
/* NOTREACHED */
case MSG_DETACH:
case MSG_DETACHKILL:
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXITED:
imsg_free(&imsg);
return (-1);
switch (imsg->hdr.type) {
case MSG_EXIT:
case MSG_SHUTDOWN:
if (datalen != sizeof retval && datalen != 0)
fatalx("bad MSG_EXIT size");
if (datalen == sizeof retval) {
memcpy(&retval, data, sizeof retval);
client_exitval = retval;
}
proc_exit(client_proc);
break;
case MSG_READY:
if (datalen != 0)
fatalx("bad MSG_READY size");
imsg_free(&imsg);
event_del(&client_stdin);
client_attached = 1;
proc_send(client_peer, MSG_RESIZE, -1, NULL, 0);
break;
case MSG_STDIN:
if (datalen != 0)
fatalx("bad MSG_STDIN size");
event_add(&client_stdin, NULL);
break;
case MSG_STDOUT:
if (datalen != sizeof stdoutdata)
fatalx("bad MSG_STDOUT size");
memcpy(&stdoutdata, data, sizeof stdoutdata);
client_write(STDOUT_FILENO, stdoutdata.data,
stdoutdata.size);
break;
case MSG_STDERR:
if (datalen != sizeof stderrdata)
fatalx("bad MSG_STDERR size");
memcpy(&stderrdata, data, sizeof stderrdata);
client_write(STDERR_FILENO, stderrdata.data,
stderrdata.size);
break;
case MSG_VERSION:
if (datalen != 0)
fatalx("bad MSG_VERSION size");
fprintf(stderr, "protocol version mismatch "
"(client %d, server %u)\n", PROTOCOL_VERSION,
imsg->hdr.peerid & 0xff);
client_exitval = 1;
proc_exit(client_proc);
break;
case MSG_SHELL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_SHELL string");
clear_signals(0);
client_exec(data, shellcmd);
/* NOTREACHED */
case MSG_DETACH:
case MSG_DETACHKILL:
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXITED:
proc_exit(client_proc);
break;
}
}
/* Dispatch imsgs in attached state (after MSG_READY). */
int
client_dispatch_attached(void)
void
client_dispatch_attached(struct imsg *imsg)
{
struct imsg imsg;
struct sigaction sigact;
char *data;
ssize_t n, datalen;
ssize_t datalen;
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
data = imsg->data;
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
data = imsg.data;
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
switch (imsg->hdr.type) {
case MSG_DETACH:
case MSG_DETACHKILL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_DETACH string");
log_debug("got %u from server", imsg.hdr.type);
switch (imsg.hdr.type) {
case MSG_DETACH:
case MSG_DETACHKILL:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_DETACH string");
client_exitsession = xstrdup(data);
client_exittype = imsg->hdr.type;
if (imsg->hdr.type == MSG_DETACHKILL)
client_exitreason = CLIENT_EXIT_DETACHED_HUP;
else
client_exitreason = CLIENT_EXIT_DETACHED;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size");
client_exitsession = xstrdup(data);
client_exittype = imsg.hdr.type;
if (imsg.hdr.type == MSG_DETACHKILL)
client_exitreason = CLIENT_EXIT_DETACHED_HUP;
else
client_exitreason = CLIENT_EXIT_DETACHED;
client_write_server(MSG_EXITING, NULL, 0);
break;
case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size");
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
client_exitreason = CLIENT_EXIT_EXITED;
break;
case MSG_EXITED:
if (datalen != 0)
fatalx("bad MSG_EXITED size");
client_write_server(MSG_EXITING, NULL, 0);
client_exitreason = CLIENT_EXIT_EXITED;
break;
case MSG_EXITED:
if (datalen != 0)
fatalx("bad MSG_EXITED size");
proc_exit(client_proc);
break;
case MSG_SHUTDOWN:
if (datalen != 0)
fatalx("bad MSG_SHUTDOWN size");
imsg_free(&imsg);
return (-1);
case MSG_SHUTDOWN:
if (datalen != 0)
fatalx("bad MSG_SHUTDOWN size");
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
client_exitreason = CLIENT_EXIT_SERVER_EXITED;
client_exitval = 1;
break;
case MSG_SUSPEND:
if (datalen != 0)
fatalx("bad MSG_SUSPEND size");
client_write_server(MSG_EXITING, NULL, 0);
client_exitreason = CLIENT_EXIT_SERVER_EXITED;
client_exitval = 1;
break;
case MSG_SUSPEND:
if (datalen != 0)
fatalx("bad MSG_SUSPEND size");
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_LOCK string");
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_DFL;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
kill(getpid(), SIGTSTP);
break;
case MSG_LOCK:
if (datalen == 0 || data[datalen - 1] != '\0')
fatalx("bad MSG_LOCK string");
system(data);
client_write_server(MSG_UNLOCK, NULL, 0);
break;
}
imsg_free(&imsg);
system(data);
proc_send(client_peer, MSG_UNLOCK, -1, NULL, 0);
break;
}
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,52 +33,35 @@
enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
"c:dErt:", 0, 0,
"[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
CMD_STARTSERVER,
cmd_attach_session_exec
.name = "attach-session",
.alias = "attach",
.args = { "c:dErt:", 0, 0 },
.usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION_WITHPANE,
.flags = CMD_STARTSERVER,
.exec = cmd_attach_session_exec
};
enum cmd_retval
cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
const char *cflag, int Eflag)
cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag,
int Eflag)
{
struct session *s;
struct session *s = cmdq->state.tflag.s;
struct client *c = cmdq->client, *c_loop;
struct winlink *wl = NULL;
struct window *w = NULL;
struct window_pane *wp = NULL;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
const char *update;
char *cause;
int fd;
char *cause, *cwd;
struct format_tree *ft;
char *cp;
if (RB_EMPTY(&sessions)) {
cmdq_error(cmdq, "no sessions");
return (CMD_RETURN_ERROR);
}
if (tflag == NULL) {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
} else if (tflag[strcspn(tflag, ":.")] != '\0') {
if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
} else {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
w = window_find_by_id_str(tflag);
if (w == NULL) {
wp = window_pane_find_by_id_str(tflag);
if (wp != NULL)
w = wp->window;
}
if (w != NULL)
wl = winlink_find_by_window(&s->windows, w);
}
if (c == NULL)
return (CMD_RETURN_NORMAL);
if (server_client_check_nested(c)) {
@@ -94,45 +77,32 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
}
if (cflag != NULL) {
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s,
NULL, NULL);
cp = format_expand(ft, cflag);
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, wp);
cwd = format_expand(ft, cflag);
format_free(ft);
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
close(s->cwd);
s->cwd = fd;
free((void *)s->cwd);
s->cwd = cwd;
}
if (c->session != NULL) {
if (dflag) {
/*
* Can't use server_write_session in case attaching to
* the same session as currently attached to.
*/
TAILQ_FOREACH(c_loop, &clients, entry) {
if (c_loop->session != s || c == c_loop)
continue;
server_write_client(c, MSG_DETACH,
c_loop->session->name,
strlen(c_loop->session->name) + 1);
server_client_detach(c_loop, MSG_DETACH);
}
}
if (!Eflag) {
update = options_get_string(&s->options,
update = options_get_string(s->options,
"update-environment");
environ_update(update, &c->environ, &s->environ);
environ_update(update, c->environ, s->environ);
}
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
@@ -150,17 +120,21 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
c->flags |= CLIENT_READONLY;
if (dflag) {
server_write_session(s, MSG_DETACH, s->name,
strlen(s->name) + 1);
TAILQ_FOREACH(c_loop, &clients, entry) {
if (c_loop->session != s || c == c_loop)
continue;
server_client_detach(c_loop, MSG_DETACH);
}
}
if (!Eflag) {
update = options_get_string(&s->options,
update = options_get_string(s->options,
"update-environment");
environ_update(update, &c->environ, &s->environ);
environ_update(update, c->environ, s->environ);
}
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
@@ -168,10 +142,13 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
server_write_ready(c);
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
hooks_run(c->session->hooks, c, NULL, "client-attached");
cmdq->client_exit = 0;
}
recalculate_sizes();
alerts_check_session(s);
server_update_socket();
return (CMD_RETURN_NORMAL);
@@ -182,7 +159,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
return (cmd_attach_session(cmdq, args_get(args, 't'),
args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c'),
args_has(args, 'E')));
return (cmd_attach_session(cmdq, args_has(args, 'd'),
args_has(args, 'r'), args_get(args, 'c'), args_has(args, 'E')));
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,14 +29,19 @@
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_bind_key_mode_table(struct cmd *, struct cmd_q *, int);
enum cmd_retval cmd_bind_key_mode_table(struct cmd *, struct cmd_q *,
key_code);
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
"cnrt:T:", 1, -1,
"[-cnr] [-t mode-table] [-T key-table] key command [arguments]",
0,
cmd_bind_key_exec
.name = "bind-key",
.alias = "bind",
.args = { "cnrt:T:", 1, -1 },
.usage = "[-cnr] [-t mode-table] [-T key-table] key command "
"[arguments]",
.flags = 0,
.exec = cmd_bind_key_exec
};
enum cmd_retval
@@ -45,7 +50,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
char *cause;
struct cmd_list *cmdlist;
int key;
key_code key;
const char *tablename;
if (args_has(args, 't')) {
@@ -61,7 +66,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
@@ -89,7 +94,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
{
struct args *args = self->args;
const char *tablename;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,39 +31,39 @@
enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp",
"dPF:s:t:", 0, 0,
"[-dP] [-F format] " CMD_SRCDST_PANE_USAGE,
0,
cmd_break_pane_exec
.name = "break-pane",
.alias = "breakp",
.args = { "dPF:s:t:", 0, 0 },
.usage = "[-dP] [-F format] [-s src-pane] [-t dst-window]",
.sflag = CMD_PANE,
.tflag = CMD_WINDOW_INDEX,
.flags = 0,
.exec = cmd_break_pane_exec
};
enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct session *src_s;
struct session *dst_s;
struct window_pane *wp;
struct window *w;
struct winlink *wl = cmdq->state.sflag.wl;
struct session *src_s = cmdq->state.sflag.s;
struct session *dst_s = cmdq->state.tflag.s;
struct window_pane *wp = cmdq->state.sflag.wp;
struct window *w = wl->window;
char *name;
char *cause;
int idx;
int idx = cmdq->state.tflag.idx;
struct format_tree *ft;
const char *template;
char *cp;
wl = cmd_find_pane(cmdq, args_get(args, 's'), &src_s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst_s)) == -2)
return (CMD_RETURN_ERROR);
if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
cmdq_error(cmdq, "index %d already in use", idx);
return (CMD_RETURN_ERROR);
}
w = wl->window;
if (window_count_panes(w) == 1) {
cmdq_error(cmdq, "can't break with only one pane");
@@ -82,9 +82,10 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
window_set_name(w, name);
free(name);
layout_init(w, wp);
wp->flags |= PANE_CHANGED;
if (idx == -1)
idx = -1 - options_get_number(&dst_s->options, "base-index");
idx = -1 - options_get_number(dst_s->options, "base-index");
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
if (!args_has(self->args, 'd'))
session_select(dst_s, wl->idx);
@@ -100,9 +101,8 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = BREAK_PANE_TEMPLATE;
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), dst_s, wl,
wp);
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, dst_s, wl, wp);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);

View File

@@ -36,12 +36,17 @@ char *cmd_capture_pane_history(struct args *, struct cmd_q *,
struct window_pane *, size_t *);
const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep",
"ab:CeE:JpPqS:t:", 0, 0,
"[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] [-S start-line]"
CMD_TARGET_PANE_USAGE,
0,
cmd_capture_pane_exec
.name = "capture-pane",
.alias = "capturep",
.args = { "ab:CeE:JpPqS:t:", 0, 0 },
.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
"[-S start-line]" CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_capture_pane_exec
};
char *
@@ -175,14 +180,11 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct window_pane *wp;
struct window_pane *wp = cmdq->state.tflag.wp;
char *buf, *cause;
const char *bufname;
size_t len;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
len = 0;
if (args_has(args, 'P'))
buf = cmd_capture_pane_pending(args, wp, &len);
@@ -203,7 +205,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
free(buf);
if (args_has(args, 'P') && len > 0)
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
server_client_push_stdout(c);
} else {
bufname = NULL;
if (args_has(args, 'b'))

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,27 +33,31 @@
enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_buffer_entry = {
"choose-buffer", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
cmd_choose_buffer_exec
.name = "choose-buffer",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_buffer_exec
};
enum cmd_retval
cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_choose_data *cdata;
struct winlink *wl;
struct paste_buffer *pb;
char *action, *action_data;
const char *template;
u_int idx;
int utf8flag;
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
@@ -61,10 +65,6 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = CHOOSE_BUFFER_TEMPLATE;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
utf8flag = options_get_number(&wl->window->options, "utf8");
if (paste_get_top(NULL) == NULL)
return (CMD_RETURN_NORMAL);
@@ -83,7 +83,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
cdata->idx = idx;
cdata->ft_template = xstrdup(template);
format_defaults_paste_buffer(cdata->ft, pb, utf8flag);
format_defaults_paste_buffer(cdata->ft, pb);
xasprintf(&action_data, "%s", paste_buffer_name(pb));
cdata->command = cmd_template_replace(action, action_data, 1);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,18 +31,23 @@
"#{client_tty}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}]" \
"#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \
"(last used #{client_activity_string})"
"(last used #{t:client_activity})"
enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_q *);
void cmd_choose_client_callback(struct window_choose_data *);
const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
cmd_choose_client_exec
.name = "choose-client",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_client_exec
};
struct cmd_choose_client_data {
@@ -53,22 +58,19 @@ enum cmd_retval
cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct client *c1;
struct window_choose_data *cdata;
struct winlink *wl;
struct winlink *wl = cmdq->state.tflag.wl;
const char *template;
char *action;
u_int idx, cur;
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);

View File

@@ -44,37 +44,52 @@
enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_tree_entry = {
"choose-tree", NULL,
"S:W:swub:c:t:", 0, 1,
"[-suw] [-b session-template] [-c window template] [-S format] " \
"[-W format] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_choose_tree_exec
.name = "choose-tree",
.alias = NULL,
.args = { "S:W:swub:c:t:", 0, 1 },
.usage = "[-suw] [-b session-template] [-c window template] "
"[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_tree_exec
};
const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
cmd_choose_tree_exec
.name = "choose-session",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_tree_exec
};
const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
0,
cmd_choose_tree_exec
.name = "choose-window",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_tree_exec
};
enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl, *wm;
struct session *s, *s2;
struct client *c;
struct client *c = cmdq->state.c;
struct winlink *wl = cmdq->state.tflag.wl, *wm;
struct session *s = cmdq->state.tflag.s, *s2;
struct window_choose_data *wcd = NULL;
const char *ses_template, *win_template;
char *final_win_action, *cur_win_template;
@@ -87,14 +102,11 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
ses_template = win_template = NULL;
ses_action = win_action = NULL;
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,23 +27,25 @@
enum cmd_retval cmd_clear_history_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist",
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
cmd_clear_history_exec
.name = "clear-history",
.alias = "clearhist",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_clear_history_exec
};
enum cmd_retval
cmd_clear_history_exec(struct cmd *self, struct cmd_q *cmdq)
cmd_clear_history_exec(__unused struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
struct window_pane *wp = cmdq->state.tflag.wp;
struct grid *gd;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
gd = wp->base.grid;
gd = cmdq->state.tflag.wp->base.grid;
if (wp->mode == &window_copy_mode)
window_pane_reset_mode(wp);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,11 +35,17 @@ int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_free(void *);
const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL,
"I:p:t:", 0, 1,
"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
0,
cmd_command_prompt_exec
.name = "command-prompt",
.alias = NULL,
.args = { "I:p:t:", 0, 1 },
.usage = "[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
"[template]",
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_command_prompt_exec
};
struct cmd_command_prompt_cdata {
@@ -58,13 +64,10 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
const char *inputs, *prompts;
struct cmd_command_prompt_cdata *cdata;
struct client *c;
struct client *c = cmdq->state.c;
char *prompt, *ptr, *input = NULL;
size_t n;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (c->prompt_string != NULL)
return (CMD_RETURN_NORMAL);

View File

@@ -34,11 +34,16 @@ int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *);
const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm",
"p:t:", 1, 1,
"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
0,
cmd_confirm_before_exec
.name = "confirm-before",
.alias = "confirm",
.args = { "p:t:", 1, 1 },
.usage = "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_confirm_before_exec
};
struct cmd_confirm_before_data {
@@ -51,13 +56,10 @@ cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct cmd_confirm_before_data *cdata;
struct client *c;
struct client *c = cmdq->state.c;
char *cmd, *copy, *new_prompt, *ptr;
const char *prompt;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if ((prompt = args_get(args, 'p')) != NULL)
xasprintf(&new_prompt, "%s ", prompt);
else {

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,19 +27,29 @@
enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL,
"Met:u", 0, 0,
"[-Meu] " CMD_TARGET_PANE_USAGE,
0,
cmd_copy_mode_exec
.name = "copy-mode",
.alias = NULL,
.args = { "Met:u", 0, 0 },
.usage = "[-Mu] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_copy_mode_exec
};
const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL,
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
cmd_copy_mode_exec
.name = "clock-mode",
.alias = NULL,
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_copy_mode_exec
};
enum cmd_retval
@@ -48,15 +58,14 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
struct client *c = cmdq->client;
struct session *s;
struct window_pane *wp;
struct window_pane *wp = cmdq->state.tflag.wp;
if (args_has(args, 'M')) {
if ((wp = cmd_mouse_pane(&cmdq->item->mouse, &s, NULL)) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
} else if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
}
if (self->entry == &cmd_clock_mode_entry) {
window_pane_set_mode(wp, &window_clock_mode);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,35 +29,44 @@
enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach",
"as:t:P", 0, 0,
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
CMD_READONLY,
cmd_detach_client_exec
.name = "detach-client",
.alias = "detach",
.args = { "as:t:P", 0, 0 },
.usage = "[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
.sflag = CMD_SESSION,
.tflag = CMD_CLIENT,
.flags = CMD_READONLY,
.exec = cmd_detach_client_exec
};
const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
cmd_detach_client_exec
.name = "suspend-client",
.alias = "suspendc",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_detach_client_exec
};
enum cmd_retval
cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c, *cloop;
struct client *c = cmdq->state.c, *cloop;
struct session *s;
enum msgtype msgtype;
if (self->entry == &cmd_suspend_client_entry) {
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
tty_stop_tty(&c->tty);
c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_SUSPEND, NULL, 0);
proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0);
return (CMD_RETURN_NORMAL);
}
@@ -67,36 +76,22 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
msgtype = MSG_DETACH;
if (args_has(args, 's')) {
s = cmd_find_session(cmdq, args_get(args, 's'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
s = cmdq->state.sflag.s;
TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session != s)
continue;
server_write_client(cloop, msgtype,
cloop->session->name,
strlen(cloop->session->name) + 1);
if (cloop->session == s)
server_client_detach(cloop, msgtype);
}
return (CMD_RETURN_STOP);
}
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) {
TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session == NULL || cloop == c)
continue;
server_write_client(cloop, msgtype,
cloop->session->name,
strlen(cloop->session->name) + 1);
if (cloop->session != NULL && cloop != c)
server_client_detach(cloop, msgtype);
}
return (CMD_RETURN_NORMAL);
}
server_write_client(c, msgtype, c->session->name,
strlen(c->session->name) + 1);
server_client_detach(c, msgtype);
return (CMD_RETURN_STOP);
}

View File

@@ -35,70 +35,47 @@
enum cmd_retval cmd_display_message_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_display_message_entry = {
"display-message", "display",
"c:pt:F:", 0, 1,
"[-p] [-c target-client] [-F format] " CMD_TARGET_PANE_USAGE
" [message]",
0,
cmd_display_message_exec
.name = "display-message",
.alias = "display",
.args = { "c:pt:F:", 0, 1 },
.usage = "[-p] [-c target-client] [-F format] "
CMD_TARGET_PANE_USAGE " [message]",
.cflag = CMD_CLIENT_CANFAIL,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_display_message_exec
};
enum cmd_retval
cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s;
struct winlink *wl;
struct window_pane *wp;
struct client *c = cmdq->state.c;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
const char *template;
char *msg;
struct format_tree *ft;
char out[BUFSIZ];
time_t t;
size_t len;
if (args_has(args, 't')) {
wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
} else {
wl = cmd_find_pane(cmdq, NULL, &s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'F') && args->argc != 0) {
cmdq_error(cmdq, "only one of -F or argument must be given");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'c')) {
c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
} else {
c = cmd_find_client(cmdq, NULL, 1);
if (c == NULL && !args_has(self->args, 'p')) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
}
template = args_get(args, 'F');
if (args->argc != 0)
template = args->argv[0];
if (template == NULL)
template = DISPLAY_MESSAGE_TEMPLATE;
ft = format_create();
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, wp);
t = time(NULL);
len = strftime(out, sizeof out, template, localtime(&t));
out[len] = '\0';
msg = format_expand(ft, out);
msg = format_expand_time(ft, template, time(NULL));
if (args_has(self->args, 'p'))
cmdq_print(cmdq, "%s", msg);
else

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,23 +27,22 @@
enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
cmd_display_panes_exec
.name = "display-panes",
.alias = "displayp",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_display_panes_exec
};
enum cmd_retval
cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq)
cmd_display_panes_exec(__unused struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
server_set_identify(c);
server_set_identify(cmdq->state.c);
return (CMD_RETURN_NORMAL);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -48,11 +48,16 @@ void cmd_find_window_callback(struct window_choose_data *);
CMD_FIND_WINDOW_BY_NAME)
const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw",
"F:CNt:T", 1, 4,
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
0,
cmd_find_window_exec
.name = "find-window",
.alias = "findw",
.args = { "F:CNt:T", 1, 4 },
.usage = "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_find_window_exec
};
struct cmd_find_window_data {
@@ -137,10 +142,10 @@ enum cmd_retval
cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct window_choose_data *cdata;
struct session *s;
struct winlink *wl, *wm;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl, *wm;
struct cmd_find_window_list find_list;
struct cmd_find_window_data *find_data;
struct cmd_find_window_data *find_data1;
@@ -148,14 +153,10 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
const char *template;
u_int i, match_flags;
if ((c = cmd_find_client(cmdq, NULL, 1)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
s = c->session;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if ((template = args_get(args, 'F')) == NULL)
template = FIND_WINDOW_TEMPLATE;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -22,34 +22,11 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
#define CMD_FIND_PREFER_UNATTACHED 0x1
#define CMD_FIND_QUIET 0x2
#define CMD_FIND_WINDOW_INDEX 0x4
#define CMD_FIND_DEFAULT_MARKED 0x8
#define CMD_FIND_EXACT_SESSION 0x10
#define CMD_FIND_EXACT_WINDOW 0x20
enum cmd_find_type {
CMD_FIND_PANE,
CMD_FIND_WINDOW,
CMD_FIND_SESSION,
};
struct cmd_find_state {
struct cmd_q *cmdq;
int flags;
struct cmd_find_state *current;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
int idx;
};
struct session *cmd_find_try_TMUX(struct client *, struct window *);
int cmd_find_client_better(struct client *, struct client *);
struct client *cmd_find_best_client(struct client **, u_int);
int cmd_find_session_better(struct session *, struct session *,
@@ -72,12 +49,6 @@ int cmd_find_get_pane(struct cmd_find_state *, const char *);
int cmd_find_get_pane_with_session(struct cmd_find_state *, const char *);
int cmd_find_get_pane_with_window(struct cmd_find_state *, const char *);
void cmd_find_clear_state(struct cmd_find_state *, struct cmd_q *, int);
void cmd_find_log_state(const char *, const char *, struct cmd_find_state *);
struct cmd_find_state *cmd_find_target(struct cmd_q *, const char *,
enum cmd_find_type, int);
const char *cmd_find_session_table[][2] = {
{ NULL, NULL }
};
@@ -108,6 +79,33 @@ const char *cmd_find_pane_table[][2] = {
{ NULL, NULL }
};
/* Get session from TMUX if present. */
struct session *
cmd_find_try_TMUX(struct client *c, struct window *w)
{
struct environ_entry *envent;
char tmp[256];
long long pid;
u_int session;
struct session *s;
envent = environ_find(c->environ, "TMUX");
if (envent == NULL)
return (NULL);
if (sscanf(envent->value, "%255[^,],%lld,%d", tmp, &pid, &session) != 3)
return (NULL);
if (pid != getpid())
return (NULL);
log_debug("client %p TMUX is %s (session @%u)", c, envent->value,
session);
s = session_find_by_id(session);
if (s == NULL || (w != NULL && !session_has(s, w)))
return (NULL);
return (s);
}
/* Is this client better? */
int
cmd_find_client_better(struct client *c, struct client *than)
@@ -191,6 +189,12 @@ cmd_find_best_session_with_window(struct cmd_find_state *fs)
u_int ssize;
struct session *s;
if (fs->cmdq != NULL && fs->cmdq->client != NULL) {
fs->s = cmd_find_try_TMUX(fs->cmdq->client, fs->w);
if (fs->s != NULL)
return (cmd_find_best_winlink_with_window(fs));
}
ssize = 0;
RB_FOREACH(s, sessions, &sessions) {
if (!session_has(s, fs->w))
@@ -244,8 +248,12 @@ cmd_find_current_session_with_client(struct cmd_find_state *fs)
{
struct window_pane *wp;
/* If this is running in a pane, that's great. */
if (fs->cmdq->client->tty.path != NULL) {
/*
* If this is running in a pane, we can use that to limit the list of
* sessions to those containing that pane (we still use the current
* window in the best session).
*/
if (fs->cmdq != NULL && fs->cmdq->client->tty.path != NULL) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
if (strcmp(wp->tty, fs->cmdq->client->tty.path) == 0)
break;
@@ -254,24 +262,44 @@ cmd_find_current_session_with_client(struct cmd_find_state *fs)
wp = NULL;
/* Not running in a pane. We know nothing. Find the best session. */
if (wp == NULL) {
fs->s = cmd_find_best_session(NULL, 0, fs->flags);
if (fs->s == NULL)
return (-1);
fs->wl = fs->s->curw;
fs->idx = fs->wl->idx;
fs->w = fs->wl->window;
fs->wp = fs->w->active;
return (0);
if (wp == NULL)
goto unknown_pane;
/* Find the best session and winlink containing this pane. */
fs->w = wp->window;
if (cmd_find_best_session_with_window(fs) != 0) {
if (wp != NULL) {
/*
* The window may have been destroyed but the pane
* still on all_window_panes due to something else
* holding a reference.
*/
goto unknown_pane;
}
return (-1);
}
/* We now know the window and pane. */
fs->w = wp->window;
fs->wp = wp;
/* Use the current window and pane from this session. */
fs->wl = fs->s->curw;
fs->idx = fs->wl->idx;
fs->w = fs->wl->window;
fs->wp = fs->w->active;
/* Find the best session and winlink. */
if (cmd_find_best_session_with_window(fs) != 0)
return (0);
unknown_pane:
fs->s = NULL;
if (fs->cmdq != NULL)
fs->s = cmd_find_try_TMUX(fs->cmdq->client, NULL);
if (fs->s == NULL)
fs->s = cmd_find_best_session(NULL, 0, fs->flags);
if (fs->s == NULL)
return (-1);
fs->wl = fs->s->curw;
fs->idx = fs->wl->idx;
fs->w = fs->wl->window;
fs->wp = fs->w->active;
return (0);
}
@@ -283,7 +311,9 @@ int
cmd_find_current_session(struct cmd_find_state *fs)
{
/* If we know the current client, use it. */
if (fs->cmdq->client != NULL) {
if (fs->cmdq != NULL && fs->cmdq->client != NULL) {
log_debug("%s: have client %p%s", __func__, fs->cmdq->client,
fs->cmdq->client->session == NULL ? "" : " (with session)");
if (fs->cmdq->client->session == NULL)
return (cmd_find_current_session_with_client(fs));
fs->s = fs->cmdq->client->session;
@@ -316,8 +346,11 @@ cmd_find_current_client(struct cmd_q *cmdq)
u_int csize;
/* If the queue client has a session, use it. */
if (cmdq->client != NULL && cmdq->client->session != NULL)
if (cmdq->client != NULL && cmdq->client->session != NULL) {
log_debug("%s: using cmdq %p client %p", __func__, cmdq,
cmdq->client);
return (cmdq->client);
}
/* Otherwise find the current session. */
cmd_find_clear_state(&current, cmdq, 0);
@@ -326,6 +359,7 @@ cmd_find_current_client(struct cmd_q *cmdq)
/* If it is attached, find the best of it's clients. */
s = current.s;
log_debug("%s: current session $%u %s", __func__, s->id, s->name);
if (~s->flags & SESSION_UNATTACHED) {
csize = 0;
TAILQ_FOREACH(c, &clients, entry) {
@@ -366,6 +400,7 @@ int
cmd_find_get_session(struct cmd_find_state *fs, const char *session)
{
struct session *s, *s_loop;
struct client *c;
log_debug("%s: %s", __func__, session);
@@ -382,6 +417,13 @@ cmd_find_get_session(struct cmd_find_state *fs, const char *session)
if (fs->s != NULL)
return (0);
/* Look for as a client. */
c = cmd_find_client(NULL, session, 1);
if (c != NULL && c->session != NULL) {
fs->s = c->session;
return (0);
}
/* Stop now if exact only. */
if (fs->flags & CMD_FIND_EXACT_SESSION)
return (-1);
@@ -440,11 +482,10 @@ cmd_find_get_window(struct cmd_find_state *fs, const char *window)
/* Otherwise try as a session itself. */
if (cmd_find_get_session(fs, window) == 0) {
if (~fs->flags & CMD_FIND_WINDOW_INDEX) {
fs->wl = fs->s->curw;
fs->w = fs->wl->window;
fs->wl = fs->s->curw;
fs->w = fs->wl->window;
if (~fs->flags & CMD_FIND_WINDOW_INDEX)
fs->idx = fs->wl->idx;
}
return (0);
}
@@ -466,6 +507,13 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
log_debug("%s: %s", __func__, window);
exact = (fs->flags & CMD_FIND_EXACT_WINDOW);
/*
* Start with the current window as the default. So if only an index is
* found, the window will be the current.
*/
fs->wl = fs->s->curw;
fs->w = fs->wl->window;
/* Check for window ids starting with @. */
if (*window == '@') {
fs->w = window_find_by_id_str(window);
@@ -762,34 +810,168 @@ cmd_find_clear_state(struct cmd_find_state *fs, struct cmd_q *cmdq, int flags)
fs->idx = -1;
}
/* Split target into pieces and resolve for the given type. */
struct cmd_find_state *
cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
int flags)
/* Check if a state if valid. */
int
cmd_find_valid_state(struct cmd_find_state *fs)
{
static struct cmd_find_state fs, current;
struct mouse_event *m;
char *colon, *period, *copy = NULL;
const char *session, *window, *pane;
struct winlink *wl;
/* Find current state. */
cmd_find_clear_state(&current, cmdq, flags);
if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) {
current.s = marked_session;
current.wl = marked_winlink;
current.idx = current.wl->idx;
current.w = current.wl->window;
current.wp = marked_window_pane;
if (fs->s == NULL || fs->wl == NULL || fs->w == NULL || fs->wp == NULL)
return (0);
if (!session_alive(fs->s))
return (0);
RB_FOREACH(wl, winlinks, &fs->s->windows) {
if (wl->window == fs->w && wl == fs->wl)
break;
}
if (current.s == NULL && cmd_find_current_session(&current) != 0) {
if (wl == NULL)
return (0);
if (fs->w != fs->wl->window)
return (0);
if (!window_has_pane(fs->w, fs->wp))
return (0);
return (window_pane_visible(fs->wp));
}
/* Copy a state. */
void
cmd_find_copy_state(struct cmd_find_state *dst, struct cmd_find_state *src)
{
dst->s = src->s;
dst->wl = src->wl;
dst->idx = src->idx;
dst->w = src->w;
dst->wp = src->wp;
}
/* Log the result. */
void
cmd_find_log_state(const char *prefix, struct cmd_find_state *fs)
{
if (fs->s != NULL)
log_debug("%s: s=$%u", prefix, fs->s->id);
else
log_debug("%s: s=none", prefix);
if (fs->wl != NULL) {
log_debug("%s: wl=%u %d w=@%u %s", prefix, fs->wl->idx,
fs->wl->window == fs->w, fs->w->id, fs->w->name);
} else
log_debug("%s: wl=none", prefix);
if (fs->wp != NULL)
log_debug("%s: wp=%%%u", prefix, fs->wp->id);
else
log_debug("%s: wp=none", prefix);
if (fs->idx != -1)
log_debug("%s: idx=%d", prefix, fs->idx);
else
log_debug("%s: idx=none", prefix);
}
/* Find state from a session. */
int
cmd_find_from_session(struct cmd_find_state *fs, struct session *s)
{
cmd_find_clear_state(fs, NULL, 0);
fs->s = s;
fs->wl = fs->s->curw;
fs->w = fs->wl->window;
fs->wp = fs->w->active;
cmd_find_log_state(__func__, fs);
return (0);
}
/* Find state from a winlink. */
int
cmd_find_from_winlink(struct cmd_find_state *fs, struct session *s,
struct winlink *wl)
{
cmd_find_clear_state(fs, NULL, 0);
fs->s = s;
fs->wl = wl;
fs->w = wl->window;
fs->wp = wl->window->active;
cmd_find_log_state(__func__, fs);
return (0);
}
/* Find state from a window. */
int
cmd_find_from_window(struct cmd_find_state *fs, struct window *w)
{
cmd_find_clear_state(fs, NULL, 0);
fs->w = w;
if (cmd_find_best_session_with_window(fs) != 0)
return (-1);
if (cmd_find_best_winlink_with_window(fs) != 0)
return (-1);
cmd_find_log_state(__func__, fs);
return (0);
}
/* Find state from a pane. */
int
cmd_find_from_pane(struct cmd_find_state *fs, struct window_pane *wp)
{
if (cmd_find_from_window(fs, wp->window) != 0)
return (-1);
fs->wp = wp;
cmd_find_log_state(__func__, fs);
return (0);
}
/* Find current state. */
int
cmd_find_current(struct cmd_find_state *fs, struct cmd_q *cmdq, int flags)
{
cmd_find_clear_state(fs, cmdq, flags);
if (cmd_find_current_session(fs) != 0) {
if (~flags & CMD_FIND_QUIET)
cmdq_error(cmdq, "no current session");
goto error;
return (-1);
}
return (0);
}
/*
* Split target into pieces and resolve for the given type. Fills in the given
* state. Returns 0 on success or -1 on error.
*/
int
cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
struct cmd_q *cmdq, const char *target, enum cmd_find_type type, int flags)
{
struct mouse_event *m;
char *colon, *period, *copy = NULL;
const char *session, *window, *pane;
/* Log the arguments. */
if (target == NULL)
log_debug("%s: target none, type %d", __func__, type);
else
log_debug("%s: target %s, type %d", __func__, target, type);
log_debug("%s: cmdq %p, flags %#x", __func__, cmdq, flags);
/* Clear new state. */
cmd_find_clear_state(&fs, cmdq, flags);
fs.current = &current;
cmd_find_clear_state(fs, cmdq, flags);
/* Find current state. */
if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED))
fs->current = &marked_pane;
else if (cmd_find_valid_state(&cmdq->current))
fs->current = &cmdq->current;
else
fs->current = current;
/* An empty or NULL target is the current. */
if (target == NULL || *target == '\0')
@@ -800,25 +982,25 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
m = &cmdq->item->mouse;
switch (type) {
case CMD_FIND_PANE:
fs.wp = cmd_mouse_pane(m, &fs.s, &fs.wl);
if (fs.wp != NULL)
fs.w = fs.wl->window;
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
if (fs->wp != NULL)
fs->w = fs->wl->window;
break;
case CMD_FIND_WINDOW:
case CMD_FIND_SESSION:
fs.wl = cmd_mouse_window(m, &fs.s);
if (fs.wl != NULL) {
fs.w = fs.wl->window;
fs.wp = fs.w->active;
fs->wl = cmd_mouse_window(m, &fs->s);
if (fs->wl != NULL) {
fs->w = fs->wl->window;
fs->wp = fs->w->active;
}
break;
}
if (fs.wp == NULL) {
if (fs->wp == NULL) {
if (~flags & CMD_FIND_QUIET)
cmdq_error(cmdq, "no mouse target");
goto error;
}
return (&fs);
goto found;
}
/* Marked target is a plain ~ or {marked}. */
@@ -828,12 +1010,8 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
cmdq_error(cmdq, "no marked target");
goto error;
}
fs.s = marked_session;
fs.wl = marked_winlink;
fs.idx = fs.wl->idx;
fs.w = fs.wl->window;
fs.wp = marked_window_pane;
return (&fs);
cmd_find_copy_state(fs, &marked_pane);
goto found;
}
/* Find separators if they exist. */
@@ -885,11 +1063,11 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
/* Set exact match flags. */
if (session != NULL && *session == '=') {
session++;
fs.flags |= CMD_FIND_EXACT_SESSION;
fs->flags |= CMD_FIND_EXACT_SESSION;
}
if (window != NULL && *window == '=') {
window++;
fs.flags |= CMD_FIND_EXACT_WINDOW;
fs->flags |= CMD_FIND_EXACT_WINDOW;
}
/* Empty is the same as NULL. */
@@ -922,32 +1100,31 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
/* If the session isn't NULL, look it up. */
if (session != NULL) {
/* This will fill in session. */
if (cmd_find_get_session(&fs, session) != 0)
if (cmd_find_get_session(fs, session) != 0)
goto no_session;
/* If window and pane are NULL, use that session's current. */
if (window == NULL && pane == NULL) {
fs.wl = fs.s->curw;
fs.idx = -1;
fs.w = fs.wl->window;
fs.wp = fs.w->active;
fs->wl = fs->s->curw;
fs->idx = -1;
fs->w = fs->wl->window;
fs->wp = fs->w->active;
goto found;
}
/* If window is present but pane not, find window in session. */
if (window != NULL && pane == NULL) {
/* This will fill in winlink and window. */
if (cmd_find_get_window_with_session(&fs, window) != 0)
if (cmd_find_get_window_with_session(fs, window) != 0)
goto no_window;
if (~flags & CMD_FIND_WINDOW_INDEX)
fs.wp = fs.wl->window->active;
fs->wp = fs->wl->window->active;
goto found;
}
/* If pane is present but window not, find pane. */
if (window == NULL && pane != NULL) {
/* This will fill in winlink and window and pane. */
if (cmd_find_get_pane_with_session(&fs, pane) != 0)
if (cmd_find_get_pane_with_session(fs, pane) != 0)
goto no_pane;
goto found;
}
@@ -956,10 +1133,10 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
* If window and pane are present, find both in session. This
* will fill in winlink and window.
*/
if (cmd_find_get_window_with_session(&fs, window) != 0)
if (cmd_find_get_window_with_session(fs, window) != 0)
goto no_window;
/* This will fill in pane. */
if (cmd_find_get_pane_with_window(&fs, pane) != 0)
if (cmd_find_get_pane_with_window(fs, pane) != 0)
goto no_pane;
goto found;
}
@@ -967,10 +1144,10 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
/* No session. If window and pane, try them. */
if (window != NULL && pane != NULL) {
/* This will fill in session, winlink and window. */
if (cmd_find_get_window(&fs, window) != 0)
if (cmd_find_get_window(fs, window) != 0)
goto no_window;
/* This will fill in pane. */
if (cmd_find_get_pane_with_window(&fs, pane) != 0)
if (cmd_find_get_pane_with_window(fs, pane) != 0)
goto no_pane;
goto found;
}
@@ -978,35 +1155,40 @@ cmd_find_target(struct cmd_q *cmdq, const char *target, enum cmd_find_type type,
/* If just window is present, try it. */
if (window != NULL && pane == NULL) {
/* This will fill in session, winlink and window. */
if (cmd_find_get_window(&fs, window) != 0)
if (cmd_find_get_window(fs, window) != 0)
goto no_window;
if (~flags & CMD_FIND_WINDOW_INDEX)
fs.wp = fs.wl->window->active;
fs->wp = fs->wl->window->active;
goto found;
}
/* If just pane is present, try it. */
if (window == NULL && pane != NULL) {
/* This will fill in session, winlink, window and pane. */
if (cmd_find_get_pane(&fs, pane) != 0)
if (cmd_find_get_pane(fs, pane) != 0)
goto no_pane;
goto found;
}
current:
/* None is the current session. */
free(copy);
/* Use the current session. */
cmd_find_copy_state(fs, fs->current);
if (flags & CMD_FIND_WINDOW_INDEX)
current.idx = -1;
return (&current);
fs->idx = -1;
goto found;
error:
fs->current = NULL;
log_debug(" error");
free(copy);
return (NULL);
return (-1);
found:
fs->current = NULL;
cmd_find_log_state(__func__, fs);
free(copy);
return (&fs);
return (0);
no_session:
if (~flags & CMD_FIND_QUIET)
@@ -1024,139 +1206,6 @@ no_pane:
goto error;
}
/* Log the result. */
void
cmd_find_log_state(const char *f, const char *target, struct cmd_find_state *fs)
{
log_debug("%s: target %s%s", f, target == NULL ? "none" : target,
fs != NULL ? "" : " (failed)");
if (fs == NULL)
return;
if (fs->s != NULL)
log_debug("\ts=$%u", fs->s->id);
else
log_debug("\ts=none");
if (fs->wl != NULL) {
log_debug("\twl=%u %d w=@%u %s", fs->wl->idx,
fs->wl->window == fs->w, fs->w->id, fs->w->name);
} else
log_debug("\twl=none");
if (fs->wp != NULL)
log_debug("\twp=%%%u", fs->wp->id);
else
log_debug("\twp=none");
if (fs->idx != -1)
log_debug("\tidx=%d", fs->idx);
else
log_debug("\tidx=none");
}
/* Find the current session. */
struct session *
cmd_find_current(struct cmd_q *cmdq)
{
struct cmd_find_state *fs;
int flags = CMD_FIND_QUIET;
fs = cmd_find_target(cmdq, NULL, CMD_FIND_SESSION, flags);
cmd_find_log_state(__func__, NULL, fs);
if (fs == NULL)
return (NULL);
return (fs->s);
}
/* Find the target session or report an error and return NULL. */
struct session *
cmd_find_session(struct cmd_q *cmdq, const char *target, int prefer_unattached)
{
struct cmd_find_state *fs;
int flags = 0;
if (prefer_unattached)
flags |= CMD_FIND_PREFER_UNATTACHED;
fs = cmd_find_target(cmdq, target, CMD_FIND_SESSION, flags);
cmd_find_log_state(__func__, target, fs);
if (fs == NULL)
return (NULL);
return (fs->s);
}
/* Find the target window or report an error and return NULL. */
struct winlink *
cmd_find_window(struct cmd_q *cmdq, const char *target, struct session **sp)
{
struct cmd_find_state *fs;
fs = cmd_find_target(cmdq, target, CMD_FIND_WINDOW, 0);
cmd_find_log_state(__func__, target, fs);
if (fs == NULL)
return (NULL);
if (sp != NULL)
*sp = fs->s;
return (fs->wl);
}
/* Find the target window, defaulting to marked rather than current. */
struct winlink *
cmd_find_window_marked(struct cmd_q *cmdq, const char *target,
struct session **sp)
{
struct cmd_find_state *fs;
int flags = CMD_FIND_DEFAULT_MARKED;
fs = cmd_find_target(cmdq, target, CMD_FIND_WINDOW, flags);
cmd_find_log_state(__func__, target, fs);
if (fs == NULL)
return (NULL);
if (sp != NULL)
*sp = fs->s;
return (fs->wl);
}
/* Find the target pane and report an error and return NULL. */
struct winlink *
cmd_find_pane(struct cmd_q *cmdq, const char *target, struct session **sp,
struct window_pane **wpp)
{
struct cmd_find_state *fs;
fs = cmd_find_target(cmdq, target, CMD_FIND_PANE, 0);
cmd_find_log_state(__func__, target, fs);
if (fs == NULL)
return (NULL);
if (sp != NULL)
*sp = fs->s;
if (wpp != NULL)
*wpp = fs->wp;
return (fs->wl);
}
/* Find the target pane, defaulting to marked rather than current. */
struct winlink *
cmd_find_pane_marked(struct cmd_q *cmdq, const char *target,
struct session **sp, struct window_pane **wpp)
{
struct cmd_find_state *fs;
int flags = CMD_FIND_DEFAULT_MARKED;
fs = cmd_find_target(cmdq, target, CMD_FIND_PANE, flags);
cmd_find_log_state(__func__, target, fs);
if (fs == NULL)
return (NULL);
if (sp != NULL)
*sp = fs->s;
if (wpp != NULL)
*wpp = fs->wp;
return (fs->wl);
}
/* Find the target client or report an error and return NULL. */
struct client *
cmd_find_client(struct cmd_q *cmdq, const char *target, int quiet)
@@ -1167,10 +1216,11 @@ cmd_find_client(struct cmd_q *cmdq, const char *target, int quiet)
const char *path;
/* A NULL argument means the current client. */
if (target == NULL) {
if (cmdq != NULL && target == NULL) {
c = cmd_find_current_client(cmdq);
if (c == NULL && !quiet)
cmdq_error(cmdq, "no current client");
log_debug("%s: no target, return %p", __func__, c);
return (c);
}
copy = xstrdup(target);
@@ -1202,27 +1252,6 @@ cmd_find_client(struct cmd_q *cmdq, const char *target, int quiet)
cmdq_error(cmdq, "can't find client %s", copy);
free(copy);
log_debug("%s: target %s, return %p", __func__, target, c);
return (c);
}
/*
* 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_q *cmdq, const char *target, struct session **sp)
{
struct cmd_find_state *fs;
int flags = CMD_FIND_WINDOW_INDEX;
fs = cmd_find_target(cmdq, target, CMD_FIND_WINDOW, flags);
cmd_find_log_state(__func__, target, fs);
if (fs == NULL)
return (-2);
if (sp != NULL)
*sp = fs->s;
return (fs->idx);
}

View File

@@ -36,11 +36,17 @@ void cmd_if_shell_done(struct cmd_q *);
void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
"bFt:", 2, 3,
"[-bF] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0,
cmd_if_shell_exec
.name = "if-shell",
.alias = "if",
.args = { "bFt:", 2, 3 },
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
"[command]",
.tflag = CMD_PANE_CANFAIL,
.flags = 0,
.exec = cmd_if_shell_exec
};
struct cmd_if_shell_data {
@@ -61,32 +67,20 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
struct cmd_if_shell_data *cdata;
char *shellcmd, *cmd, *cause;
struct cmd_list *cmdlist;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
struct window_pane *wp = NULL;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
struct format_tree *ft;
int cwd;
const char *cwd;
if (args_has(args, 't')) {
wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
cwd = wp->cwd;
} else {
c = cmd_find_client(cmdq, NULL, 1);
if (c != NULL && c->session != NULL) {
s = c->session;
wl = s->curw;
wp = wl->window->active;
}
if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else if (s != NULL)
cwd = s->cwd;
else
cwd = -1;
}
if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else if (s != NULL)
cwd = s->cwd;
else
cwd = NULL;
ft = format_create();
ft = format_create(cmdq, 0);
format_defaults(ft, NULL, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
format_free(ft);
@@ -97,6 +91,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
cmd = args->argv[1];
else if (args->argc == 3)
cmd = args->argv[2];
free(shellcmd);
if (cmd == NULL)
return (CMD_RETURN_NORMAL);
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {

View File

@@ -2,7 +2,7 @@
/*
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,19 +33,31 @@ enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmd_q *);
enum cmd_retval join_pane(struct cmd *, struct cmd_q *, int);
const struct cmd_entry cmd_join_pane_entry = {
"join-pane", "joinp",
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
0,
cmd_join_pane_exec
.name = "join-pane",
.alias = "joinp",
.args = { "bdhvp:l:s:t:", 0, 0 },
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE_MARKED,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_join_pane_exec
};
const struct cmd_entry cmd_move_pane_entry = {
"move-pane", "movep",
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
0,
cmd_join_pane_exec
.name = "move-pane",
.alias = "movep",
.args = { "bdhvp:l:s:t:", 0, 0 },
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_join_pane_exec
};
enum cmd_retval
@@ -67,16 +79,15 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
enum layout_type type;
struct layout_cell *lc;
dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), &dst_s, &dst_wp);
if (dst_wl == NULL)
return (CMD_RETURN_ERROR);
dst_s = cmdq->state.tflag.s;
dst_wl = cmdq->state.tflag.wl;
dst_wp = cmdq->state.tflag.wp;
dst_w = dst_wl->window;
dst_idx = dst_wl->idx;
server_unzoom_window(dst_w);
src_wl = cmd_find_pane_marked(cmdq, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
src_wl = cmdq->state.sflag.wl;
src_wp = cmdq->state.sflag.wp;
src_w = src_wl->window;
server_unzoom_window(src_w);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,22 +29,24 @@
enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp",
"at:", 0, 0,
"[-a] " CMD_TARGET_PANE_USAGE,
0,
cmd_kill_pane_exec
.name = "kill-pane",
.alias = "killp",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_kill_pane_exec
};
enum cmd_retval
cmd_kill_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window_pane *loopwp, *tmpwp, *wp;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *loopwp, *tmpwp, *wp = cmdq->state.tflag.wp;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
server_unzoom_window(wl->window);
if (window_count_panes(wl->window) == 1) {

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,23 +30,29 @@
enum cmd_retval cmd_kill_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL,
"", 0, 0,
"",
0,
cmd_kill_server_exec
.name = "kill-server",
.alias = NULL,
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
.exec = cmd_kill_server_exec
};
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"", 0, 0,
"",
CMD_STARTSERVER,
cmd_kill_server_exec
.name = "start-server",
.alias = "start",
.args = { "", 0, 0 },
.usage = "",
.flags = CMD_STARTSERVER,
.exec = cmd_kill_server_exec
};
enum cmd_retval
cmd_kill_server_exec(struct cmd *self, unused struct cmd_q *cmdq)
cmd_kill_server_exec(struct cmd *self, __unused struct cmd_q *cmdq)
{
if (self->entry == &cmd_kill_server_entry)
kill(getpid(), SIGTERM);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,11 +30,16 @@
enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL,
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_kill_session_exec
.name = "kill-session",
.alias = NULL,
.args = { "aCt:", 0, 0 },
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_kill_session_exec
};
enum cmd_retval
@@ -42,11 +47,17 @@ cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s, *sloop, *stmp;
struct winlink *wl;
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
s = cmdq->state.tflag.s;
if (args_has(args, 'a')) {
if (args_has(args, 'C')) {
RB_FOREACH(wl, winlinks, &s->windows) {
wl->window->flags &= ~WINDOW_ALERTFLAGS;
wl->flags &= ~WINLINK_ALERTFLAGS;
}
server_redraw_session(s);
} else if (args_has(args, 'a')) {
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
if (sloop != s) {
server_destroy_session(sloop);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,32 +27,38 @@
enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw",
"at:", 0, 0,
"[-a] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_kill_window_exec
.name = "kill-window",
.alias = "killw",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_kill_window_exec
};
const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw",
"kt:", 0, 0,
"[-k] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_kill_window_exec
.name = "unlink-window",
.alias = "unlinkw",
.args = { "kt:", 0, 0 },
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_kill_window_exec
};
enum cmd_retval
cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl, *wl2, *wl3;
struct window *w;
struct session *s;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
struct args *args = self->args;
struct winlink *wl = cmdq->state.tflag.wl, *wl2, *wl3;
struct window *w = wl->window;
struct session *s = cmdq->state.tflag.s;
if (self->entry == &cmd_unlink_window_entry) {
if (!args_has(self->args, 'k') && !session_is_linked(s, w)) {

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,15 +33,18 @@
enum cmd_retval cmd_list_buffers_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb",
"F:", 0, 0,
"[-F format]",
0,
cmd_list_buffers_exec
.name = "list-buffers",
.alias = "lsb",
.args = { "F:", 0, 0 },
.usage = "[-F format]",
.flags = 0,
.exec = cmd_list_buffers_exec
};
enum cmd_retval
cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
cmd_list_buffers_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct paste_buffer *pb;
@@ -54,8 +57,8 @@ cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
pb = NULL;
while ((pb = paste_walk(pb)) != NULL) {
ft = format_create();
format_defaults_paste_buffer(ft, pb, 0);
ft = format_create(cmdq, 0);
format_defaults_paste_buffer(ft, pb);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -36,11 +36,16 @@
enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc",
"F:t:", 0, 0,
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
cmd_list_clients_exec
.name = "list-clients",
.alias = "lsc",
.args = { "F:t:", 0, 0 },
.usage = "[-F format] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = CMD_READONLY,
.exec = cmd_list_clients_exec
};
enum cmd_retval
@@ -54,11 +59,9 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq)
u_int idx;
char *line;
if (args_has(args, 't')) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
} else
if (args_has(args, 't'))
s = cmdq->state.tflag.s;
else
s = NULL;
if ((template = args_get(args, 'F')) == NULL)
@@ -69,7 +72,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq)
if (c->session == NULL || (s != NULL && s != c->session))
continue;
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", idx);
format_defaults(ft, c, NULL, NULL, NULL);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,6 +18,7 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@@ -29,22 +30,28 @@
enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_list_keys_commands(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_list_keys_commands(struct cmd_q *);
const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk",
"t:T:", 0, 0,
"[-t mode-table] [-T key-table]",
0,
cmd_list_keys_exec
.name = "list-keys",
.alias = "lsk",
.args = { "t:T:", 0, 0 },
.usage = "[-t mode-table] [-T key-table]",
.flags = CMD_STARTSERVER,
.exec = cmd_list_keys_exec
};
const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm",
"", 0, 0,
"",
0,
cmd_list_keys_exec
.name = "list-commands",
.alias = "lscm",
.args = { "", 0, 0 },
.usage = "",
.flags = CMD_STARTSERVER,
.exec = cmd_list_keys_exec
};
enum cmd_retval
@@ -54,12 +61,11 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
struct key_table *table;
struct key_binding *bd;
const char *key, *tablename, *r;
char tmp[BUFSIZ];
size_t used;
char *cp, tmp[BUFSIZ];
int repeat, width, tablewidth, keywidth;
if (self->entry == &cmd_list_commands_entry)
return (cmd_list_keys_commands(self, cmdq));
return (cmd_list_keys_commands(cmdq));
if (args_has(args, 't'))
return (cmd_list_keys_table(self, cmdq));
@@ -77,16 +83,14 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
continue;
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
key = key_string_lookup_key(bd->key);
if (key == NULL)
continue;
if (bd->can_repeat)
repeat = 1;
width = strlen(table->name);
width = utf8_cstrwidth(table->name);
if (width > tablewidth)
tablewidth =width;
width = strlen(key);
tablewidth = width;
width = utf8_cstrwidth(key);
if (width > keywidth)
keywidth = width;
}
@@ -97,8 +101,6 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
continue;
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
key = key_string_lookup_key(bd->key);
if (key == NULL)
continue;
if (!repeat)
r = "";
@@ -106,12 +108,21 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
r = "-r ";
else
r = " ";
used = xsnprintf(tmp, sizeof tmp, "%s-T %-*s %-*s ", r,
(int)tablewidth, table->name, (int)keywidth, key);
if (used < sizeof tmp) {
cmd_list_print(bd->cmdlist, tmp + used,
(sizeof tmp) - used);
}
xsnprintf(tmp, sizeof tmp, "%s-T ", r);
cp = utf8_padcstr(table->name, tablewidth);
strlcat(tmp, cp, sizeof tmp);
strlcat(tmp, " ", sizeof tmp);
free(cp);
cp = utf8_padcstr(key, keywidth);
strlcat(tmp, cp, sizeof tmp);
strlcat(tmp, " ", sizeof tmp);
free(cp);
cp = cmd_list_print(bd->cmdlist);
strlcat(tmp, cp, sizeof tmp);
free(cp);
cmdq_print(cmdq, "bind-key %s", tmp);
}
@@ -140,8 +151,6 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
any_mode = 0;
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
if (mbind->mode != 0)
any_mode = 1;
@@ -153,8 +162,6 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
mode = "";
if (mbind->mode != 0)
@@ -174,7 +181,7 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
cmd_list_keys_commands(unused struct cmd *self, struct cmd_q *cmdq)
cmd_list_keys_commands(struct cmd_q *cmdq)
{
const struct cmd_entry **entryp;
const struct cmd_entry *entry;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,33 +35,31 @@ void cmd_list_panes_window(struct cmd *, struct session *, struct winlink *,
struct cmd_q *, int);
const struct cmd_entry cmd_list_panes_entry = {
"list-panes", "lsp",
"asF:t:", 0, 0,
"[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_list_panes_exec
.name = "list-panes",
.alias = "lsp",
.args = { "asF:t:", 0, 0 },
.usage = "[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_list_panes_exec
};
enum cmd_retval
cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
if (args_has(args, 'a'))
cmd_list_panes_server(self, cmdq);
else if (args_has(args, 's')) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
else if (args_has(args, 's'))
cmd_list_panes_session(self, s, cmdq, 1);
} else {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
else
cmd_list_panes_window(self, s, wl, cmdq, 0);
}
return (CMD_RETURN_NORMAL);
}
@@ -125,7 +123,7 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", n);
format_defaults(ft, NULL, s, wl, wp);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,7 +30,7 @@
#define LIST_SESSIONS_TEMPLATE \
"#{session_name}: #{session_windows} windows " \
"(created #{session_created_string}) " \
"(created #{t:session_created}) " \
"[#{session_width}x#{session_height}]" \
"#{?session_grouped, (group ,}" \
"#{session_group}#{?session_grouped,),}" \
@@ -39,11 +39,14 @@
enum cmd_retval cmd_list_sessions_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls",
"F:", 0, 0,
"[-F format]",
0,
cmd_list_sessions_exec
.name = "list-sessions",
.alias = "ls",
.args = { "F:", 0, 0 },
.usage = "[-F format]",
.flags = 0,
.exec = cmd_list_sessions_exec
};
enum cmd_retval
@@ -61,7 +64,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmd_q *cmdq)
n = 0;
RB_FOREACH(s, sessions, &sessions) {
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", n);
format_defaults(ft, NULL, s, NULL, NULL);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -46,27 +46,27 @@ void cmd_list_windows_session(struct cmd *, struct session *,
struct cmd_q *, int);
const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw",
"F:at:", 0, 0,
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
0,
cmd_list_windows_exec
.name = "list-windows",
.alias = "lsw",
.args = { "F:at:", 0, 0 },
.usage = "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_list_windows_exec
};
enum cmd_retval
cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
if (args_has(args, 'a'))
cmd_list_windows_server(self, cmdq);
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
cmd_list_windows_session(self, s, cmdq, 0);
}
else
cmd_list_windows_session(self, cmdq->state.tflag.s, cmdq, 0);
return (CMD_RETURN_NORMAL);
}
@@ -81,8 +81,8 @@ cmd_list_windows_server(struct cmd *self, struct cmd_q *cmdq)
}
void
cmd_list_windows_session(
struct cmd *self, struct session *s, struct cmd_q *cmdq, int type)
cmd_list_windows_session(struct cmd *self, struct session *s,
struct cmd_q *cmdq, int type)
{
struct args *args = self->args;
struct winlink *wl;
@@ -105,7 +105,7 @@ cmd_list_windows_session(
n = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", n);
format_defaults(ft, NULL, s, wl, NULL);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -99,25 +99,28 @@ cmd_list_free(struct cmd_list *cmdlist)
free(cmdlist);
}
size_t
cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
char *
cmd_list_print(struct cmd_list *cmdlist)
{
struct cmd *cmd;
size_t off, used;
char *buf, *this;
size_t len;
len = 1;
buf = xcalloc(1, len);
off = 0;
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (off >= len)
break;
off += cmd_print(cmd, buf + off, len - off);
if (off >= len)
break;
if (TAILQ_NEXT(cmd, qentry) != NULL) {
used = xsnprintf(buf + off, len - off, " ; ");
if (used > len - off)
used = len - off;
off += used;
}
this = cmd_print(cmd);
len += strlen(this) + 3;
buf = xrealloc(buf, len);
strlcat(buf, this, len);
if (TAILQ_NEXT(cmd, qentry) != NULL)
strlcat(buf, " ; ", len);
free(this);
}
return (off);
return (buf);
}

View File

@@ -35,11 +35,14 @@ enum cmd_retval cmd_load_buffer_exec(struct cmd *, struct cmd_q *);
void cmd_load_buffer_callback(struct client *, int, void *);
const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb",
"b:", 1, 1,
CMD_BUFFER_USAGE " path",
0,
cmd_load_buffer_exec
.name = "load-buffer",
.alias = "loadb",
.args = { "b:", 1, 1 },
.usage = CMD_BUFFER_USAGE " path",
.flags = 0,
.exec = cmd_load_buffer_exec
};
enum cmd_retval
@@ -49,10 +52,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
FILE *f;
const char *path, *bufname;
char *pdata, *new_pdata, *cause;
const char *path, *bufname, *cwd;
char *pdata, *new_pdata, *cause, *file, resolved[PATH_MAX];
size_t psize;
int ch, error, cwd, fd;
int ch, error;
bufname = NULL;
if (args_has(args, 'b'))
@@ -70,18 +73,26 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_WAIT);
}
if (c != NULL && c->session == NULL)
if (c != NULL && c->session == NULL && c->cwd != NULL)
cwd = c->cwd;
else if ((s = cmd_find_current(cmdq)) != NULL)
else if ((s = c->session) != NULL && s->cwd != NULL)
cwd = s->cwd;
else
cwd = AT_FDCWD;
cwd = ".";
if ((fd = openat(cwd, path, O_RDONLY)) == -1 ||
(f = fdopen(fd, "rb")) == NULL) {
if (fd != -1)
close(fd);
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
if (*path == '/')
file = xstrdup(path);
else
xasprintf(&file, "%s/%s", cwd, path);
if (realpath(file, resolved) == NULL &&
strlcpy(resolved, file, sizeof resolved) >= sizeof resolved) {
cmdq_error(cmdq, "%s: %s", file, strerror(ENAMETOOLONG));
return (CMD_RETURN_ERROR);
}
f = fopen(resolved, "rb");
free(file);
if (f == NULL) {
cmdq_error(cmdq, "%s: %s", resolved, strerror(errno));
return (CMD_RETURN_ERROR);
}
@@ -97,7 +108,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
pdata[psize++] = ch;
}
if (ferror(f)) {
cmdq_error(cmdq, "%s: read error", path);
cmdq_error(cmdq, "%s: read error", resolved);
goto error;
}
if (pdata != NULL)
@@ -125,7 +136,7 @@ void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
const char *bufname = data;
char *pdata, *cause;
char *pdata, *cause, *saved;
size_t psize;
if (!closed)
@@ -146,8 +157,13 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data)
if (paste_set(pdata, psize, bufname, &cause) != 0) {
/* No context so can't use server_client_msg_error. */
if (~c->flags & CLIENT_UTF8) {
saved = cause;
cause = utf8_sanitize(saved);
free(saved);
}
evbuffer_add_printf(c->stderr_data, "%s", cause);
server_push_stderr(c);
server_client_push_stderr(c);
free(pdata);
free(cause);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,49 +27,52 @@
enum cmd_retval cmd_lock_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock",
"", 0, 0,
"",
0,
cmd_lock_server_exec
.name = "lock-server",
.alias = "lock",
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
.exec = cmd_lock_server_exec
};
const struct cmd_entry cmd_lock_session_entry = {
"lock-session", "locks",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
cmd_lock_server_exec
.name = "lock-session",
.alias = "locks",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_lock_server_exec
};
const struct cmd_entry cmd_lock_client_entry = {
"lock-client", "lockc",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
cmd_lock_server_exec
.name = "lock-client",
.alias = "lockc",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_lock_server_exec
};
enum cmd_retval
cmd_lock_server_exec(struct cmd *self, unused struct cmd_q *cmdq)
cmd_lock_server_exec(struct cmd *self, __unused struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s;
if (self->entry == &cmd_lock_server_entry)
server_lock();
else if (self->entry == &cmd_lock_session_entry) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
server_lock_session(s);
} else {
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
server_lock_client(c);
}
else if (self->entry == &cmd_lock_session_entry)
server_lock_session(cmdq->state.tflag.s);
else
server_lock_client(cmdq->state.c);
recalculate_sizes();
return (CMD_RETURN_NORMAL);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,55 +29,59 @@
enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew",
"adkrs:t:", 0, 0,
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
cmd_move_window_exec
.name = "move-window",
.alias = "movew",
.args = { "adkrs:t:", 0, 0 },
.usage = "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
.sflag = CMD_WINDOW,
.tflag = CMD_MOVEW_R,
.flags = 0,
.exec = cmd_move_window_exec
};
const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw",
"adks:t:", 0, 0,
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
cmd_move_window_exec
.name = "link-window",
.alias = "linkw",
.args = { "adks:t:", 0, 0 },
.usage = "[-dk] " CMD_SRCDST_WINDOW_USAGE,
.sflag = CMD_WINDOW,
.tflag = CMD_WINDOW_INDEX,
.flags = 0,
.exec = cmd_move_window_exec
};
enum cmd_retval
cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *src, *dst, *s;
struct winlink *wl;
struct session *src = cmdq->state.sflag.s;
struct session *dst = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.sflag.wl;
char *cause;
int idx, kflag, dflag, sflag;
int idx = cmdq->state.tflag.idx, kflag, dflag, sflag;
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
if (args_has(args, 'r')) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
session_renumber_windows(s);
session_renumber_windows(dst);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
}
if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL)
return (CMD_RETURN_ERROR);
if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2)
return (CMD_RETURN_ERROR);
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
sflag = args_has(self->args, 's');
if (args_has(self->args, 'a')) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
if ((idx = winlink_shuffle_up(s, s->curw)) == -1)
if ((idx = winlink_shuffle_up(dst, dst->curw)) == -1)
return (CMD_RETURN_ERROR);
}
@@ -95,7 +99,7 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
* session already has the correct winlink id to us, either
* automatically or specified by -s.
*/
if (!sflag && options_get_number(&src->options, "renumber-windows"))
if (!sflag && options_get_number(src->options, "renumber-windows"))
session_renumber_windows(src);
recalculate_sizes();

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -36,44 +36,56 @@
enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
"Ac:dDEF:n:Ps:t:x:y:", 0, -1,
"[-AdDEP] [-c start-directory] [-F format] [-n window-name] "
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
"[-y height] [command]",
CMD_STARTSERVER,
cmd_new_session_exec
.name = "new-session",
.alias = "new",
.args = { "Ac:dDEF:n:Ps:t:x:y:", 0, -1 },
.usage = "[-AdDEP] [-c start-directory] [-F format] [-n window-name] "
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
"[-y height] [command]",
.tflag = CMD_SESSION_CANFAIL,
.flags = CMD_STARTSERVER,
.exec = cmd_new_session_exec
};
const struct cmd_entry cmd_has_session_entry = {
"has-session", "has",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
cmd_new_session_exec
.name = "has-session",
.alias = "has",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_new_session_exec
};
enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c = cmdq->client, *c0;
struct session *s, *groupwith;
struct client *c = cmdq->client;
struct session *s, *as;
struct session *groupwith = cmdq->state.tflag.s;
struct window *w;
struct environ env;
struct environ *env;
struct termios tio, *tiop;
const char *newname, *target, *update, *errstr, *template;
const char *path;
const char *path, *cwd, *to_free = NULL;
char **argv, *cmd, *cause, *cp;
int detached, already_attached, idx, cwd, fd = -1;
int argc;
int detached, already_attached, idx, argc;
u_int sx, sy;
struct format_tree *ft;
struct environ_entry *envent;
if (self->entry == &cmd_has_session_entry) {
if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL)
return (CMD_RETURN_ERROR);
/*
* cmd_prepare() will fail if the session cannot be found,
* hence always return success here.
*/
return (CMD_RETURN_NORMAL);
}
@@ -88,9 +100,16 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "bad session name: %s", newname);
return (CMD_RETURN_ERROR);
}
if (session_find(newname) != NULL) {
if ((as = session_find(newname)) != NULL) {
if (args_has(args, 'A')) {
return (cmd_attach_session(cmdq, newname,
/*
* This cmdq is now destined for
* attach-session. Because attach-session
* will have already been prepared, copy this
* session into its tflag so it can be used.
*/
cmd_find_from_session(&cmdq->state.tflag, as);
return (cmd_attach_session(cmdq,
args_has(args, 'D'), 0, NULL,
args_has(args, 'E')));
}
@@ -99,11 +118,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
}
}
target = args_get(args, 't');
if (target != NULL) {
groupwith = cmd_find_session(cmdq, target, 0);
if (groupwith == NULL)
return (CMD_RETURN_ERROR);
if ((target = args_get(args, 't')) != NULL) {
if (groupwith == NULL) {
cmdq_error(cmdq, "no such session: %s", target);
goto error;
}
} else
groupwith = NULL;
@@ -119,31 +138,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Get the new session working directory. */
if (args_has(args, 'c')) {
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), NULL, NULL,
NULL);
cp = format_expand(ft, args_get(args, 'c'));
ft = format_create(cmdq, 0);
format_defaults(ft, c, NULL, NULL, NULL);
to_free = cwd = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (c != NULL && c->session == NULL)
} else if (c != NULL && c->session == NULL && c->cwd != NULL)
cwd = c->cwd;
else if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
cwd = c0->session->cwd;
else {
fd = open(".", O_RDONLY);
cwd = fd;
}
else
cwd = ".";
/*
* If this is a new client, check for nesting and save the termios
@@ -197,7 +199,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
goto error;
}
}
if (sy > 0 && options_get_number(&global_s_options, "status"))
if (sy > 0 && options_get_number(global_s_options, "status"))
sy--;
if (sx == 0)
sx = 1;
@@ -207,11 +209,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Figure out the command for the new window. */
argc = -1;
argv = NULL;
if (target == NULL && args->argc != 0) {
if (!args_has(args, 't') && args->argc != 0) {
argc = args->argc;
argv = args->argv;
} else if (target == NULL) {
cmd = options_get_string(&global_s_options, "default-command");
} else if (groupwith == NULL) {
cmd = options_get_string(global_s_options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
argv = &cmd;
@@ -223,36 +225,36 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
path = NULL;
if (c != NULL && c->session == NULL)
envent = environ_find(&c->environ, "PATH");
envent = environ_find(c->environ, "PATH");
else
envent = environ_find(&global_environ, "PATH");
envent = environ_find(global_environ, "PATH");
if (envent != NULL)
path = envent->value;
/* Construct the environment. */
environ_init(&env);
env = environ_create();
if (c != NULL && !args_has(args, 'E')) {
update = options_get_string(&global_s_options,
update = options_get_string(global_s_options,
"update-environment");
environ_update(update, &c->environ, &env);
environ_update(update, c->environ, env);
}
/* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index");
s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
idx = -1 - options_get_number(global_s_options, "base-index");
s = session_create(newname, argc, argv, path, cwd, env, tiop, idx, sx,
sy, &cause);
environ_free(env);
if (s == NULL) {
cmdq_error(cmdq, "create session failed: %s", cause);
free(cause);
goto error;
}
environ_free(&env);
/* Set the initial window name if one given. */
if (argc >= 0 && args_has(args, 'n')) {
w = s->curw->window;
window_set_name(w, args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0);
options_set_number(w->options, "automatic-rename", 0);
}
/*
@@ -270,11 +272,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
* taking this session and needs to get MSG_READY and stay around.
*/
if (!detached) {
if (!already_attached)
server_write_ready(c);
else if (c->session != NULL)
if (!already_attached) {
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
} else if (c->session != NULL)
c->last_session = c->session;
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
@@ -296,9 +300,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = NEW_SESSION_TEMPLATE;
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
NULL);
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, NULL, NULL);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
@@ -310,12 +313,12 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (!detached)
cmdq->client_exit = 0;
if (fd != -1)
close(fd);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_NORMAL);
error:
if (fd != -1)
close(fd);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_ERROR);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,43 +35,43 @@
enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww",
"ac:dF:kn:Pt:", 0, -1,
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
CMD_TARGET_WINDOW_USAGE " [command]",
0,
cmd_new_window_exec
.name = "new-window",
.alias = "neww",
.args = { "ac:dF:kn:Pt:", 0, -1 },
.usage = "[-adkP] [-c start-directory] [-F format] [-n window-name] "
CMD_TARGET_WINDOW_USAGE " [command]",
.tflag = CMD_WINDOW_INDEX,
.flags = 0,
.exec = cmd_new_window_exec
};
enum cmd_retval
cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
const char *cmd, *path, *template;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct client *c = cmdq->state.c;
int idx = cmdq->state.tflag.idx;
const char *cmd, *path, *template, *cwd, *to_free;
char **argv, *cause, *cp;
int argc, idx, detached, cwd, fd = -1;
int argc, detached;
struct format_tree *ft;
struct environ_entry *envent;
if (args_has(args, 'a')) {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
if ((idx = winlink_shuffle_up(s, wl)) == -1) {
cmdq_error(cmdq, "no free window indexes");
return (CMD_RETURN_ERROR);
}
} else {
idx = cmd_find_index(cmdq, args_get(args, 't'), &s);
if (idx == -2)
return (CMD_RETURN_ERROR);
}
detached = args_has(args, 'd');
if (args->argc == 0) {
cmd = options_get_string(&s->options, "default-command");
cmd = options_get_string(s->options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
argv = (char **)&cmd;
@@ -86,30 +86,18 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(&cmdq->client->environ, "PATH");
envent = environ_find(cmdq->client->environ, "PATH");
else
envent = environ_find(&s->environ, "PATH");
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
to_free = NULL;
if (args_has(args, 'c')) {
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
NULL);
cp = format_expand(ft, args_get(args, 'c'));
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, NULL, NULL);
cwd = to_free = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
@@ -136,7 +124,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
idx = -1 - options_get_number(s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
&cause);
if (wl == NULL) {
@@ -154,9 +142,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = NEW_WINDOW_TEMPLATE;
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, wl,
NULL);
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, NULL);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
@@ -165,12 +152,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
if (fd != -1)
close(fd);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_NORMAL);
error:
if (fd != -1)
close(fd);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_ERROR);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -33,27 +33,29 @@ void cmd_paste_buffer_filter(struct window_pane *,
const char *, size_t, const char *, int);
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
"db:prs:t:", 0, 0,
"[-dpr] [-s separator] " CMD_BUFFER_USAGE " " CMD_TARGET_PANE_USAGE,
0,
cmd_paste_buffer_exec
.name = "paste-buffer",
.alias = "pasteb",
.args = { "db:prs:t:", 0, 0 },
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_paste_buffer_exec
};
enum cmd_retval
cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
struct session *s;
struct window_pane *wp = cmdq->state.tflag.wp;
struct paste_buffer *pb;
const char *sepstr, *bufname, *bufdata, *bufend, *line;
size_t seplen, bufsize;
int bracket = args_has(args, 'p');
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -37,29 +37,30 @@ enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmd_q *);
void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
const struct cmd_entry cmd_pipe_pane_entry = {
"pipe-pane", "pipep",
"ot:", 0, 1,
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_pipe_pane_exec
.name = "pipe-pane",
.alias = "pipep",
.args = { "ot:", 0, 1 },
.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_pipe_pane_exec
};
enum cmd_retval
cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s;
struct winlink *wl;
struct window_pane *wp;
struct client *c = cmdq->state.c;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
char *cmd;
int old_fd, pipe_fd[2], null_fd;
struct format_tree *ft;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
c = cmd_find_client(cmdq, NULL, 1);
/* Destroy the old pipe. */
old_fd = wp->pipe_fd;
if (wp->pipe_fd != -1) {
@@ -88,7 +89,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
}
/* Expand the command. */
ft = format_create();
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, wp);
cmd = format_expand_time(ft, args->argv[0], time(NULL));
format_free(ft);
@@ -141,8 +142,8 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
}
void
cmd_pipe_pane_error_callback(
unused struct bufferevent *bufev, unused short what, void *data)
cmd_pipe_pane_error_callback(__unused struct bufferevent *bufev,
__unused short what, void *data)
{
struct window_pane *wp = data;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -25,7 +25,7 @@
#include "tmux.h"
enum cmd_retval cmdq_continue_one(struct cmd_q *);
static enum cmd_retval cmdq_continue_one(struct cmd_q *);
/* Create new command queue. */
struct cmd_q *
@@ -44,6 +44,9 @@ cmdq_new(struct client *c)
cmdq->item = NULL;
cmdq->cmd = NULL;
cmd_find_clear_state(&cmdq->current, NULL, 0);
cmdq->parent = NULL;
return (cmdq);
}
@@ -69,16 +72,23 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
struct client *c = cmdq->client;
struct window *w;
va_list ap;
char *tmp, *msg;
va_start(ap, fmt);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
if (~c->flags & CLIENT_UTF8) {
vasprintf(&tmp, fmt, ap);
msg = utf8_sanitize(tmp);
free(tmp);
evbuffer_add(c->stdout_data, msg, strlen(msg));
free(msg);
} else
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
server_client_push_stdout(c);
} else {
w = c->session->curw->window;
if (w->active->mode != &window_copy_mode) {
@@ -101,6 +111,7 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
va_list ap;
char *msg;
size_t msglen;
char *tmp;
va_start(ap, fmt);
msglen = xvasprintf(&msg, fmt, ap);
@@ -109,10 +120,15 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
if (c == NULL)
cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
if (~c->flags & CLIENT_UTF8) {
tmp = msg;
msg = utf8_sanitize(tmp);
free(tmp);
msglen = strlen(msg);
}
evbuffer_add(c->stderr_data, msg, msglen);
evbuffer_add(c->stderr_data, "\n", 1);
server_push_stderr(c);
server_client_push_stderr(c);
c->retval = 1;
} else {
*msg = toupper((u_char) *msg);
@@ -133,7 +149,7 @@ cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
(long) cmdq->time, cmdq->number, flags);
server_push_stdout(c);
server_client_push_stdout(c);
}
/* Add command list to queue and begin processing if needed. */
@@ -166,36 +182,42 @@ cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
}
/* Process one command. */
enum cmd_retval
static enum cmd_retval
cmdq_continue_one(struct cmd_q *cmdq)
{
struct cmd *cmd = cmdq->cmd;
enum cmd_retval retval;
char tmp[1024];
char *tmp;
int flags = !!(cmd->flags & CMD_CONTROL);
cmd_print(cmd, tmp, sizeof tmp);
tmp = cmd_print(cmd);
log_debug("cmdq %p: %s", cmdq, tmp);
free(tmp);
cmdq->time = time(NULL);
cmdq->number++;
cmdq_guard(cmdq, "begin", flags);
if (cmd_prepare_state(cmd, cmdq, NULL) != 0)
goto error;
retval = cmd->entry->exec(cmd, cmdq);
if (retval == CMD_RETURN_ERROR)
cmdq_guard(cmdq, "error", flags);
else
cmdq_guard(cmdq, "end", flags);
goto error;
cmdq_guard(cmdq, "end", flags);
return (retval);
error:
cmdq_guard(cmdq, "error", flags);
return (CMD_RETURN_ERROR);
}
/* Continue processing command queue. Returns 1 if finishes empty. */
int
cmdq_continue(struct cmd_q *cmdq)
{
struct client *c = cmdq->client;
struct client *c = cmdq->client;
struct cmd_q_item *next;
enum cmd_retval retval;
int empty;
@@ -203,8 +225,8 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->references++;
notify_disable();
log_debug("continuing cmdq %p: flags=%#x, client=%d", cmdq, cmdq->flags,
c != NULL ? c->ibuf.fd : -1);
log_debug("continuing cmdq %p: flags %#x, client %p", cmdq, cmdq->flags,
c);
empty = TAILQ_EMPTY(&cmdq->queue);
if (empty)
@@ -267,3 +289,4 @@ cmdq_flush(struct cmd_q *cmdq)
}
cmdq->item = NULL;
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,24 +27,26 @@
enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
"C:St:", 0, 0,
"[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
0,
cmd_refresh_client_exec
.name = "refresh-client",
.alias = "refresh",
.args = { "C:St:", 0, 0 },
.usage = "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_refresh_client_exec
};
enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
const char *size;
u_int w, h;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'C')) {
if ((size = args_get(args, 'C')) == NULL) {
cmdq_error(cmdq, "missing size");

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,18 +29,23 @@
enum cmd_retval cmd_rename_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename",
"t:", 1, 1,
CMD_TARGET_SESSION_USAGE " new-name",
0,
cmd_rename_session_exec
.name = "rename-session",
.alias = "rename",
.args = { "t:", 1, 1 },
.usage = CMD_TARGET_SESSION_USAGE " new-name",
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_rename_session_exec
};
enum cmd_retval
cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct session *s = cmdq->state.tflag.s;
const char *newname;
newname = args->argv[0];
@@ -53,9 +58,6 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
RB_REMOVE(sessions, &sessions, s);
free(s->name);
s->name = xstrdup(newname);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,25 +29,26 @@
enum cmd_retval cmd_rename_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew",
"t:", 1, 1,
CMD_TARGET_WINDOW_USAGE " new-name",
0,
cmd_rename_window_exec
.name = "rename-window",
.alias = "renamew",
.args = { "t:", 1, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " new-name",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_rename_window_exec
};
enum cmd_retval
cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
struct winlink *wl = cmdq->state.tflag.wl;
window_set_name(wl->window, args->argv[0]);
options_set_number(&wl->window->options, "automatic-rename", 0);
options_set_number(wl->window->options, "automatic-rename", 0);
server_status_window(wl->window);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,25 +31,30 @@ enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_q *);
void cmd_resize_pane_mouse_update(struct client *, struct mouse_event *);
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
"DLMRt:Ux:y:Z", 0, 1,
"[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE
" [adjustment]",
0,
cmd_resize_pane_exec
.name = "resize-pane",
.alias = "resizep",
.args = { "DLMRt:Ux:y:Z", 0, 1 },
.usage = "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
"[adjustment]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_resize_pane_exec
};
enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp = cmdq->state.tflag.wp;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct client *c = cmdq->client;
struct session *s;
struct winlink *wl;
struct window *w;
struct session *s = cmdq->state.tflag.s;
const char *errstr;
char *cause;
struct window_pane *wp;
u_int adjust;
int x, y;
@@ -63,10 +68,6 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED)
window_unzoom(w);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
* Copyright (c) 2011 Marcel P. Partap <mpartap@gmx.net>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -31,31 +31,32 @@
enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_respawn_pane_entry = {
"respawn-pane", "respawnp",
"kt:", 0, -1,
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_respawn_pane_exec
.name = "respawn-pane",
.alias = "respawnp",
.args = { "kt:", 0, -1 },
.usage = "[-k] " CMD_TARGET_PANE_USAGE " [command]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_respawn_pane_exec
};
enum cmd_retval
cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct session *s;
struct environ env;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
struct environ *env;
const char *path;
char *cause;
u_int idx;
struct environ_entry *envent;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (!args_has(self->args, 'k') && wp->fd != -1) {
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
@@ -64,10 +65,10 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
env = environ_create();
environ_copy(global_environ, env);
environ_copy(s->environ, env);
server_fill_environ(s, env);
window_pane_reset_mode(wp);
screen_reinit(&wp->base);
@@ -75,22 +76,22 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(&cmdq->client->environ, "PATH");
envent = environ_find(cmdq->client->environ, "PATH");
else
envent = environ_find(&s->environ, "PATH");
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn pane failed: %s", cause);
free(cause);
environ_free(&env);
environ_free(env);
return (CMD_RETURN_ERROR);
}
wp->flags |= PANE_REDRAW;
server_status_window(w);
environ_free(&env);
environ_free(env);
return (CMD_RETURN_NORMAL);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,44 +30,45 @@
enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw",
"kt:", 0, -1,
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
0,
cmd_respawn_window_exec
.name = "respawn-window",
.alias = "respawnw",
.args = { "kt:", 0, -1 },
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_respawn_window_exec
};
enum cmd_retval
cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp;
struct session *s;
struct environ env;
struct environ *env;
const char *path;
char *cause;
struct environ_entry *envent;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (!args_has(self->args, 'k')) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1)
continue;
cmdq_error(cmdq,
"window still active: %s:%d", s->name, wl->idx);
cmdq_error(cmdq, "window still active: %s:%d", s->name,
wl->idx);
return (CMD_RETURN_ERROR);
}
}
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
env = environ_create();
environ_copy(global_environ, env);
environ_copy(s->environ, env);
server_fill_environ(s, env);
wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry);
@@ -78,18 +79,18 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(&cmdq->client->environ, "PATH");
envent = environ_find(cmdq->client->environ, "PATH");
else
envent = environ_find(&s->environ, "PATH");
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn window failed: %s", cause);
free(cause);
environ_free(&env);
server_destroy_pane(wp);
environ_free(env);
server_destroy_pane(wp, 0);
return (CMD_RETURN_ERROR);
}
layout_init(w, wp);
@@ -101,6 +102,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
server_redraw_window(w);
environ_free(&env);
environ_free(env);
return (CMD_RETURN_NORMAL);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,27 +27,27 @@
enum cmd_retval cmd_rotate_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew",
"Dt:U", 0, 0,
"[-DU] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_rotate_window_exec
.name = "rotate-window",
.alias = "rotatew",
.args = { "Dt:U", 0, 0 },
.usage = "[-DU] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_rotate_window_exec
};
enum cmd_retval
cmd_rotate_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp, *wp2;
struct layout_cell *lc;
u_int sx, sy, xoff, yoff;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (args_has(self->args, 'D')) {
wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry);

View File

@@ -36,11 +36,16 @@ void cmd_run_shell_free(void *);
void cmd_run_shell_print(struct job *, const char *);
const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run",
"bt:", 1, 1,
"[-b] " CMD_TARGET_PANE_USAGE " shell-command",
0,
cmd_run_shell_exec
.name = "run-shell",
.alias = "run",
.args = { "bt:", 1, 1 },
.usage = "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
.tflag = CMD_PANE_CANFAIL,
.flags = 0,
.exec = cmd_run_shell_exec
};
struct cmd_run_shell_data {
@@ -75,33 +80,20 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
struct cmd_run_shell_data *cdata;
char *shellcmd;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
struct window_pane *wp = NULL;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
struct format_tree *ft;
int cwd;
const char *cwd;
if (args_has(args, 't')) {
wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
cwd = wp->cwd;
} else {
c = cmd_find_client(cmdq, NULL, 1);
if (c != NULL && c->session != NULL) {
s = c->session;
wl = s->curw;
wp = wl->window->active;
}
if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else if (s != NULL)
cwd = s->cwd;
else
cwd = -1;
}
ft = format_create();
format_defaults(ft, NULL, s, wl, wp);
if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else if (s != NULL)
cwd = s->cwd;
else
cwd = NULL;
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
format_free(ft);

View File

@@ -34,19 +34,25 @@
enum cmd_retval cmd_save_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb",
"ab:", 1, 1,
"[-a] " CMD_BUFFER_USAGE " path",
0,
cmd_save_buffer_exec
.name = "save-buffer",
.alias = "saveb",
.args = { "ab:", 1, 1 },
.usage = "[-a] " CMD_BUFFER_USAGE " path",
.flags = 0,
.exec = cmd_save_buffer_exec
};
const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb",
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
cmd_save_buffer_exec
.name = "show-buffer",
.alias = "showb",
.args = { "b:", 0, 0 },
.usage = CMD_BUFFER_USAGE,
.flags = 0,
.exec = cmd_save_buffer_exec
};
enum cmd_retval
@@ -56,10 +62,10 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
struct paste_buffer *pb;
const char *path, *bufname, *bufdata, *start, *end;
char *msg;
const char *path, *bufname, *bufdata, *start, *end, *cwd;
const char *flags;
char *msg, *file, resolved[PATH_MAX];
size_t size, used, msglen, bufsize;
int cwd, fd;
FILE *f;
if (!args_has(args, 'b')) {
@@ -91,31 +97,35 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
goto do_print;
}
if (c != NULL && c->session == NULL)
if (c != NULL && c->session == NULL && c->cwd != NULL)
cwd = c->cwd;
else if ((s = cmd_find_current(cmdq)) != NULL)
else if ((s = c->session) != NULL && s->cwd != NULL)
cwd = s->cwd;
else
cwd = AT_FDCWD;
cwd = ".";
f = NULL;
if (args_has(self->args, 'a')) {
fd = openat(cwd, path, O_CREAT|O_RDWR|O_APPEND, 0600);
if (fd != -1)
f = fdopen(fd, "ab");
} else {
fd = openat(cwd, path, O_CREAT|O_RDWR|O_TRUNC, 0600);
if (fd != -1)
f = fdopen(fd, "wb");
}
if (f == NULL) {
if (fd != -1)
close(fd);
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
flags = "wb";
if (args_has(self->args, 'a'))
flags = "ab";
if (*path == '/')
file = xstrdup(path);
else
xasprintf(&file, "%s/%s", cwd, path);
if (realpath(file, resolved) == NULL &&
strlcpy(resolved, file, sizeof resolved) >= sizeof resolved) {
cmdq_error(cmdq, "%s: %s", file, strerror(ENAMETOOLONG));
return (CMD_RETURN_ERROR);
}
f = fopen(resolved, flags);
free(file);
if (f == NULL) {
cmdq_error(cmdq, "%s: %s", resolved, strerror(errno));
return (CMD_RETURN_ERROR);
}
if (fwrite(bufdata, 1, bufsize, f) != bufsize) {
cmdq_error(cmdq, "%s: fwrite error", path);
cmdq_error(cmdq, "%s: write error", resolved);
fclose(f);
return (CMD_RETURN_ERROR);
}
@@ -125,7 +135,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
do_stdout:
evbuffer_add(c->stdout_data, bufdata, bufsize);
server_push_stdout(c);
server_client_push_stdout(c);
return (CMD_RETURN_NORMAL);
do_print:

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,43 +29,55 @@
enum cmd_retval cmd_select_layout_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl",
"nopt:", 0, 1,
"[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
0,
cmd_select_layout_exec
.name = "select-layout",
.alias = "selectl",
.args = { "nopt:", 0, 1 },
.usage = "[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_layout_exec
};
const struct cmd_entry cmd_next_layout_entry = {
"next-layout", "nextl",
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_layout_exec
.name = "next-layout",
.alias = "nextl",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_layout_exec
};
const struct cmd_entry cmd_previous_layout_entry = {
"previous-layout", "prevl",
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_layout_exec
.name = "previous-layout",
.alias = "prevl",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_layout_exec
};
enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w;
const char *layoutname;
char *oldlayout;
int next, previous, layout;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
server_unzoom_window(w);
next = self->entry == &cmd_next_layout_entry;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,38 +27,44 @@
enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
"DdegLlMmP:Rt:U", 0, 0,
"[-DdegLlMmRU] [-P style] " CMD_TARGET_PANE_USAGE,
0,
cmd_select_pane_exec
.name = "select-pane",
.alias = "selectp",
.args = { "DdegLlMmP:Rt:U", 0, 0 },
.usage = "[-DdegLlMmRU] [-P style] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_select_pane_exec
};
const struct cmd_entry cmd_last_pane_entry = {
"last-pane", "lastp",
"det:", 0, 0,
"[-de] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_pane_exec
.name = "last-pane",
.alias = "lastp",
.args = { "det:", 0, 0 },
.usage = "[-de] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_pane_exec
};
enum cmd_retval
cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct session *s;
struct window_pane *wp, *lastwp, *markedwp;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct session *s = cmdq->state.tflag.s;
struct window_pane *wp = cmdq->state.tflag.wp, *lastwp, *markedwp;
const char *style;
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (w->last == NULL) {
if (wl->window->last == NULL) {
cmdq_error(cmdq, "no last pane");
return (CMD_RETURN_ERROR);
}
@@ -79,20 +85,16 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (args_has(args, 'm') || args_has(args, 'M')) {
if (args_has(args, 'm') && !window_pane_visible(wp))
return (CMD_RETURN_NORMAL);
lastwp = marked_window_pane;
lastwp = marked_pane.wp;
if (args_has(args, 'M') || server_is_marked(s, wl, wp))
server_clear_marked();
else
server_set_marked(s, wl, wp);
markedwp = marked_window_pane;
markedwp = marked_pane.wp;
if (lastwp != NULL) {
server_redraw_window_borders(lastwp->window);
@@ -120,14 +122,19 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'L'))
if (args_has(self->args, 'L')) {
server_unzoom_window(wp->window);
wp = window_pane_find_left(wp);
else if (args_has(self->args, 'R'))
} else if (args_has(self->args, 'R')) {
server_unzoom_window(wp->window);
wp = window_pane_find_right(wp);
else if (args_has(self->args, 'U'))
} else if (args_has(self->args, 'U')) {
server_unzoom_window(wp->window);
wp = window_pane_find_up(wp);
else if (args_has(self->args, 'D'))
} else if (args_has(self->args, 'D')) {
server_unzoom_window(wp->window);
wp = window_pane_find_down(wp);
}
if (wp == NULL)
return (CMD_RETURN_NORMAL);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,43 +29,62 @@
enum cmd_retval cmd_select_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw",
"lnpTt:", 0, 0,
"[-lnpT] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_window_exec
.name = "select-window",
.alias = "selectw",
.args = { "lnpTt:", 0, 0 },
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_window_exec
};
const struct cmd_entry cmd_next_window_entry = {
"next-window", "next",
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_exec
.name = "next-window",
.alias = "next",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_select_window_exec
};
const struct cmd_entry cmd_previous_window_entry = {
"previous-window", "prev",
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_exec
.name = "previous-window",
.alias = "prev",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_select_window_exec
};
const struct cmd_entry cmd_last_window_entry = {
"last-window", "last",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_exec
.name = "last-window",
.alias = "last",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_select_window_exec
};
enum cmd_retval
cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct session *s;
struct winlink *wl = cmdq->state.tflag.wl;
struct session *s = cmdq->state.tflag.s;
int next, previous, last, activity;
next = self->entry == &cmd_next_window_entry;
@@ -79,10 +98,6 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
last = 1;
if (next || previous || last) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
activity = args_has(self->args, 'a');
if (next) {
if (session_next(s, activity) != 0) {
@@ -103,10 +118,6 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
server_redraw_session(s);
} else {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
/*
* If -T and select-window is invoked on same window as
* current, switch to previous window.

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,30 +30,41 @@
enum cmd_retval cmd_send_keys_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send",
"lRMt:", 0, -1,
"[-lRM] " CMD_TARGET_PANE_USAGE " key ...",
0,
cmd_send_keys_exec
.name = "send-keys",
.alias = "send",
.args = { "lRMt:", 0, -1 },
.usage = "[-lRM] " CMD_TARGET_PANE_USAGE " key ...",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_send_keys_exec
};
const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL,
"2t:", 0, 0,
"[-2] " CMD_TARGET_PANE_USAGE,
0,
cmd_send_keys_exec
.name = "send-prefix",
.alias = NULL,
.args = { "2t:", 0, 0 },
.usage = "[-2] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_send_keys_exec
};
enum cmd_retval
cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
struct mouse_event *m = &cmdq->item->mouse;
struct window_pane *wp;
struct session *s;
const u_char *str;
int i, key;
const u_char *keystr;
int i, literal;
key_code key;
if (args_has(args, 'M')) {
wp = cmd_mouse_pane(m, &s, NULL);
@@ -65,30 +76,30 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
if (self->entry == &cmd_send_prefix_entry) {
if (args_has(args, '2'))
key = options_get_number(&s->options, "prefix2");
key = options_get_number(s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
key = options_get_number(s->options, "prefix");
window_pane_key(wp, NULL, s, key, NULL);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'R'))
input_reset(wp);
input_reset(wp, 1);
for (i = 0; i < args->argc; i++) {
str = args->argv[i];
if (!args_has(args, 'l') &&
(key = key_string_lookup_string(str)) != KEYC_NONE) {
window_pane_key(wp, NULL, s, key, NULL);
} else {
for (; *str != '\0'; str++)
window_pane_key(wp, NULL, s, *str, NULL);
literal = args_has(args, 'l');
if (!literal) {
key = key_string_lookup_string(args->argv[i]);
if (key != KEYC_NONE && key != KEYC_UNKNOWN)
window_pane_key(wp, NULL, s, key, NULL);
else
literal = 1;
}
if (literal) {
for (keystr = args->argv[i]; *keystr != '\0'; keystr++)
window_pane_key(wp, NULL, s, *keystr, NULL);
}
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,19 +30,25 @@
enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb",
"ab:n:", 0, 1,
"[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
0,
cmd_set_buffer_exec
.name = "set-buffer",
.alias = "setb",
.args = { "ab:n:", 0, 1 },
.usage = "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
.flags = 0,
.exec = cmd_set_buffer_exec
};
const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb",
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
cmd_set_buffer_exec
.name = "delete-buffer",
.alias = "deleteb",
.args = { "b:", 0, 0 },
.usage = CMD_BUFFER_USAGE,
.flags = 0,
.exec = cmd_set_buffer_exec
};
enum cmd_retval

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,20 +30,24 @@
enum cmd_retval cmd_set_environment_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv",
"grt:u", 1, 2,
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
0,
cmd_set_environment_exec
.name = "set-environment",
.alias = "setenv",
.args = { "grt:u", 1, 2 },
.usage = "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
.tflag = CMD_SESSION_CANFAIL,
.flags = 0,
.exec = cmd_set_environment_exec
};
enum cmd_retval
cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct environ *env;
const char *name, *value;
const char *name, *value, *target;
name = args->argv[0];
if (*name == '\0') {
@@ -61,11 +65,17 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
value = args->argv[1];
if (args_has(self->args, 'g'))
env = &global_environ;
env = global_environ;
else {
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
if (cmdq->state.tflag.s == NULL) {
target = args_get(args, 't');
if (target != NULL)
cmdq_error(cmdq, "no such session: %s", target);
else
cmdq_error(cmdq, "no current session");
return (CMD_RETURN_ERROR);
env = &s->environ;
}
env = cmdq->state.tflag.s->environ;
}
if (args_has(self->args, 'u')) {
@@ -79,13 +89,13 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "can't specify a value with -r");
return (CMD_RETURN_ERROR);
}
environ_set(env, name, NULL);
environ_clear(env, name);
} else {
if (value == NULL) {
cmdq_error(cmdq, "no value specified");
return (CMD_RETURN_ERROR);
}
environ_set(env, name, value);
environ_set(env, name, "%s", value);
}
return (CMD_RETURN_NORMAL);

120
cmd-set-hook.c Normal file
View File

@@ -0,0 +1,120 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Set or show global or session hooks.
*/
enum cmd_retval cmd_set_hook_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_hook_entry = {
.name = "set-hook",
.alias = NULL,
.args = { "gt:u", 1, 2 },
.usage = "[-gu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_set_hook_exec
};
const struct cmd_entry cmd_show_hooks_entry = {
.name = "show-hooks",
.alias = NULL,
.args = { "gt:", 0, 1 },
.usage = "[-g] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_set_hook_exec
};
enum cmd_retval
cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct cmd_list *cmdlist;
struct hooks *hooks;
struct hook *hook;
char *cause, *tmp;
const char *name, *cmd;
if (args_has(args, 'g'))
hooks = global_hooks;
else
hooks = cmdq->state.tflag.s->hooks;
if (self->entry == &cmd_show_hooks_entry) {
hook = hooks_first(hooks);
while (hook != NULL) {
tmp = cmd_list_print(hook->cmdlist);
cmdq_print(cmdq, "%s -> %s", hook->name, tmp);
free(tmp);
hook = hooks_next(hook);
}
return (CMD_RETURN_NORMAL);
}
name = args->argv[0];
if (*name == '\0') {
cmdq_error(cmdq, "invalid hook name");
return (CMD_RETURN_ERROR);
}
if (args->argc < 2)
cmd = NULL;
else
cmd = args->argv[1];
if (args_has(args, 'u')) {
if (cmd != NULL) {
cmdq_error(cmdq, "command passed to unset hook: %s",
name);
return (CMD_RETURN_ERROR);
}
hooks_remove(hooks, name);
return (CMD_RETURN_NORMAL);
}
if (cmd == NULL) {
cmdq_error(cmdq, "no command to set hook: %s", name);
return (CMD_RETURN_ERROR);
}
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) {
cmdq_error(cmdq, "%s", cause);
free(cause);
}
return (CMD_RETURN_ERROR);
}
hooks_add(hooks, name, cmdlist);
cmd_list_free(cmdlist);
return (CMD_RETURN_NORMAL);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -65,32 +65,42 @@ struct options_entry *cmd_set_option_style(struct cmd *, struct cmd_q *,
const char *);
const struct cmd_entry cmd_set_option_entry = {
"set-option", "set",
"agoqst:uw", 1, 2,
"[-agosquw] [-t target-session|target-window] option [value]",
0,
cmd_set_option_exec
.name = "set-option",
.alias = "set",
.args = { "agoqst:uw", 1, 2 },
.usage = "[-agosquw] [-t target-window] option [value]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_set_option_exec
};
const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw",
"agoqt:u", 1, 2,
"[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
0,
cmd_set_option_exec
.name = "set-window-option",
.alias = "setw",
.args = { "agoqt:u", 1, 2 },
.usage = "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_set_option_exec
};
enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
const struct options_table_entry *table, *oe;
struct session *s;
struct winlink *wl;
struct client *c;
struct options *oo;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w;
const char *optstr, *valstr;
struct client *c;
const struct options_table_entry *oe;
struct options *oo;
const char *optstr, *valstr, *target;
/* Get the option name and value. */
optstr = args->argv[0];
@@ -108,8 +118,8 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
return (cmd_set_option_user(self, cmdq, optstr, valstr));
/* Find the option entry, try each table. */
table = oe = NULL;
if (options_table_find(optstr, &table, &oe) != 0) {
oe = NULL;
if (options_table_find(optstr, &oe) != 0) {
if (!args_has(args, 'q')) {
cmdq_error(cmdq, "ambiguous option: %s", optstr);
return (CMD_RETURN_ERROR);
@@ -124,37 +134,35 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
/* Work out the tree from the table. */
if (table == server_options_table)
oo = &global_options;
else if (table == window_options_table) {
/* Work out the tree from the scope of the option. */
if (oe->scope == OPTIONS_TABLE_SERVER)
oo = global_options;
else if (oe->scope == OPTIONS_TABLE_WINDOW) {
if (args_has(self->args, 'g'))
oo = &global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL) {
cmdq_error(cmdq,
"couldn't set '%s'%s", optstr,
(!args_has(args, 't') && !args_has(args,
'g')) ? " need target window or -g" : "");
return (CMD_RETURN_ERROR);
}
oo = &wl->window->options;
}
} else if (table == session_options_table) {
oo = global_w_options;
else if (wl == NULL) {
target = args_get(args, 't');
if (target != NULL) {
cmdq_error(cmdq, "no such window: %s",
target);
} else
cmdq_error(cmdq, "no current window");
return (CMD_RETURN_ERROR);
} else
oo = wl->window->options;
} else if (oe->scope == OPTIONS_TABLE_SESSION) {
if (args_has(self->args, 'g'))
oo = &global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL) {
cmdq_error(cmdq,
"couldn't set '%s'%s", optstr,
(!args_has(args, 't') && !args_has(args,
'g')) ? " need target session or -g" : "");
return (CMD_RETURN_ERROR);
}
oo = &s->options;
}
oo = global_s_options;
else if (s == NULL) {
target = args_get(args, 't');
if (target != NULL) {
cmdq_error(cmdq, "no such session: %s",
target);
} else
cmdq_error(cmdq, "no current session");
return (CMD_RETURN_ERROR);
} else
oo = s->options;
} else {
cmdq_error(cmdq, "unknown table");
return (CMD_RETURN_ERROR);
@@ -179,10 +187,14 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
/* Start or stop timers if necessary. */
if (strcmp(oe->name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) {
if (options_get_number(&w->options, "automatic-rename"))
if (options_get_number(w->options, "automatic-rename"))
w->active->flags |= PANE_CHANGED;
}
}
if (strcmp(oe->name, "key-table") == 0) {
TAILQ_FOREACH(c, &clients, entry)
server_client_set_key_table(c, NULL);
}
if (strcmp(oe->name, "status") == 0 ||
strcmp(oe->name, "status-interval") == 0)
status_timer_start_all();
@@ -205,31 +217,23 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr,
const char *valstr)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct options *oo;
if (args_has(args, 's'))
oo = &global_options;
oo = global_options;
else if (args_has(self->args, 'w') ||
self->entry == &cmd_set_window_option_entry) {
if (args_has(self->args, 'g'))
oo = &global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
oo = &wl->window->options;
}
oo = global_w_options;
else
oo = wl->window->options;
} else {
if (args_has(self->args, 'g'))
oo = &global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
oo = &s->options;
}
oo = global_s_options;
else
oo = s->options;
}
if (args_has(args, 'u')) {
@@ -276,7 +280,7 @@ cmd_set_option_unset(struct cmd *self, struct cmd_q *cmdq,
return (-1);
}
if (args_has(args, 'g') || oo == &global_options) {
if (args_has(args, 'g') || oo == global_options) {
switch (oe->type) {
case OPTIONS_TABLE_STRING:
options_set_string(oo, oe->name, "%s", oe->default_str);
@@ -350,7 +354,7 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
/* Set a string option. */
struct options_entry *
cmd_set_option_string(struct cmd *self, unused struct cmd_q *cmdq,
cmd_set_option_string(struct cmd *self, __unused struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
@@ -372,7 +376,7 @@ cmd_set_option_string(struct cmd *self, unused struct cmd_q *cmdq,
/* Set a number option. */
struct options_entry *
cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_number(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
@@ -390,13 +394,14 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a key option. */
struct options_entry *
cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_key(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
int key;
key_code key;
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
key = key_string_lookup_string(value);
if (key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "bad key: %s", value);
return (NULL);
}
@@ -406,7 +411,7 @@ cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a colour option. */
struct options_entry *
cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_colour(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
@@ -422,7 +427,7 @@ cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
/* Set an attributes option. */
struct options_entry *
cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_attributes(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
@@ -438,7 +443,7 @@ cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a flag option. */
struct options_entry *
cmd_set_option_flag(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_flag(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
@@ -466,7 +471,7 @@ cmd_set_option_flag(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a choice option. */
struct options_entry *
cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_choice(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -34,11 +34,16 @@ void cmd_show_environment_print(struct cmd *, struct cmd_q *,
struct environ_entry *);
const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv",
"gst:", 0, 1,
"[-gs] " CMD_TARGET_SESSION_USAGE " [name]",
0,
cmd_show_environment_exec
.name = "show-environment",
.alias = "showenv",
.args = { "gst:", 0, 1 },
.usage = "[-gs] " CMD_TARGET_SESSION_USAGE " [name]",
.tflag = CMD_SESSION_CANFAIL,
.flags = 0,
.exec = cmd_show_environment_exec
};
char *
@@ -86,17 +91,29 @@ enum cmd_retval
cmd_show_environment_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct environ *env;
struct environ_entry *envent;
const char *target;
if ((target = args_get(args, 't')) != NULL) {
if (cmdq->state.tflag.s == NULL) {
cmdq_error(cmdq, "no such session: %s", target);
return (CMD_RETURN_ERROR);
}
}
if (args_has(self->args, 'g'))
env = &global_environ;
env = global_environ;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
if (cmdq->state.tflag.s == NULL) {
target = args_get(args, 't');
if (target != NULL)
cmdq_error(cmdq, "no such session: %s", target);
else
cmdq_error(cmdq, "no current session");
return (CMD_RETURN_ERROR);
env = &s->environ;
}
env = cmdq->state.tflag.s->environ;
}
if (args->argc != 0) {
@@ -109,7 +126,10 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
RB_FOREACH(envent, environ, env)
envent = environ_first(env);
while (envent != NULL) {
cmd_show_environment_print(self, cmdq, envent);
envent = environ_next(envent);
}
return (CMD_RETURN_NORMAL);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,41 +31,32 @@
enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs",
"IJTt:", 0, 0,
"[-IJT] " CMD_TARGET_CLIENT_USAGE,
0,
cmd_show_messages_exec
.name = "show-messages",
.alias = "showmsgs",
.args = { "JTt:", 0, 0 },
.usage = "[-JT] " CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_show_messages_exec
};
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"", 0, 0,
"",
0,
cmd_show_messages_exec
.name = "server-info",
.alias = "info",
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
.exec = cmd_show_messages_exec
};
int cmd_show_messages_server(struct cmd_q *);
int cmd_show_messages_terminals(struct cmd_q *, int);
int cmd_show_messages_jobs(struct cmd_q *, int);
int
cmd_show_messages_server(struct cmd_q *cmdq)
{
char *tim;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq, "started %s", tim);
cmdq_print(cmdq, "socket path %s", socket_path);
cmdq_print(cmdq, "debug level %d", debug_level);
cmdq_print(cmdq, "protocol version %d", PROTOCOL_VERSION);
return (1);
}
int
cmd_show_messages_terminals(struct cmd_q *cmdq, int blank)
{
@@ -110,16 +101,12 @@ enum cmd_retval
cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct message_entry *msg;
char *tim;
int done, blank;
done = blank = 0;
if (args_has(args, 'I') || self->entry == &cmd_server_info_entry) {
blank = cmd_show_messages_server(cmdq);
done = 1;
}
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
blank = cmd_show_messages_terminals(cmdq, blank);
done = 1;
@@ -131,9 +118,6 @@ cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
if (done)
return (CMD_RETURN_NORMAL);
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
TAILQ_FOREACH(msg, &c->message_log, entry) {
tim = ctime(&msg->msg_time);
*strchr(tim, '\n') = '\0';

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -32,63 +32,80 @@ enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_show_options_one(struct cmd *, struct cmd_q *,
struct options *, int);
enum cmd_retval cmd_show_options_all(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *);
struct options *, enum options_table_scope);
const struct cmd_entry cmd_show_options_entry = {
"show-options", "show",
"gqst:vw", 0, 1,
"[-gqsvw] [-t target-session|target-window] [option]",
0,
cmd_show_options_exec
.name = "show-options",
.alias = "show",
.args = { "gqst:vw", 0, 1 },
.usage = "[-gqsvw] [-t target-session|target-window] [option]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_show_options_exec
};
const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw",
"gvt:", 0, 1,
"[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
0,
cmd_show_options_exec
.name = "show-window-options",
.alias = "showw",
.args = { "gvt:", 0, 1 },
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_show_options_exec
};
enum cmd_retval
cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
const struct options_table_entry *table;
struct options *oo;
int quiet;
struct args *args = self->args;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct options *oo;
enum options_table_scope scope;
int quiet;
const char *target;
if (args_has(self->args, 's')) {
oo = &global_options;
table = server_options_table;
oo = global_options;
scope = OPTIONS_TABLE_SERVER;
} else if (args_has(self->args, 'w') ||
self->entry == &cmd_show_window_options_entry) {
table = window_options_table;
scope = OPTIONS_TABLE_WINDOW;
if (args_has(self->args, 'g'))
oo = &global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
oo = &wl->window->options;
}
oo = global_w_options;
else if (wl == NULL) {
target = args_get(args, 't');
if (target != NULL) {
cmdq_error(cmdq, "no such window: %s", target);
} else
cmdq_error(cmdq, "no current window");
return (CMD_RETURN_ERROR);
} else
oo = wl->window->options;
} else {
table = session_options_table;
scope = OPTIONS_TABLE_SESSION;
if (args_has(self->args, 'g'))
oo = &global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
oo = &s->options;
}
oo = global_s_options;
else if (s == NULL) {
target = args_get(args, 't');
if (target != NULL) {
cmdq_error(cmdq, "no such session: %s", target);
} else
cmdq_error(cmdq, "no current session");
return (CMD_RETURN_ERROR);
} else
oo = s->options;
}
quiet = args_has(self->args, 'q');
if (args->argc == 0)
return (cmd_show_options_all(self, cmdq, table, oo));
return (cmd_show_options_all(self, cmdq, oo, scope));
else
return (cmd_show_options_one(self, cmdq, oo, quiet));
}
@@ -99,7 +116,7 @@ cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq,
{
struct args *args = self->args;
const char *name = args->argv[0];
const struct options_table_entry *table, *oe;
const struct options_table_entry *oe;
struct options_entry *o;
const char *optval;
@@ -118,14 +135,14 @@ retry:
return (CMD_RETURN_NORMAL);
}
table = oe = NULL;
if (options_table_find(name, &table, &oe) != 0) {
oe = NULL;
if (options_table_find(name, &oe) != 0) {
cmdq_error(cmdq, "ambiguous option: %s", name);
return (CMD_RETURN_ERROR);
}
if (oe == NULL) {
if (quiet)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_NORMAL);
cmdq_error(cmdq, "unknown option: %s", name);
return (CMD_RETURN_ERROR);
}
@@ -144,30 +161,33 @@ retry:
}
enum cmd_retval
cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *table, struct options *oo)
cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq, struct options *oo,
enum options_table_scope scope)
{
const struct options_table_entry *oe;
struct options_entry *o;
const char *optval;
int vflag;
RB_FOREACH(o, options_tree, &oo->tree) {
o = options_first(oo);
while (o != NULL) {
if (*o->name == '@') {
if (args_has(self->args, 'v'))
cmdq_print(cmdq, "%s", o->str);
else
cmdq_print(cmdq, "%s \"%s\"", o->name, o->str);
}
o = options_next(o);
}
for (oe = table; oe->name != NULL; oe++) {
if (oe->style != NULL)
vflag = args_has(self->args, 'v');
for (oe = options_table; oe->name != NULL; oe++) {
if (oe->style != NULL || oe->scope != scope)
continue;
if ((o = options_find1(oo, oe->name)) == NULL)
continue;
optval = options_table_print_entry(oe, o,
args_has(self->args, 'v'));
if (args_has(self->args, 'v'))
optval = options_table_print_entry(oe, o, vflag);
if (vflag)
cmdq_print(cmdq, "%s", optval);
else
cmdq_print(cmdq, "%s %s", oe->name, optval);

View File

@@ -31,11 +31,14 @@ enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_q *);
void cmd_source_file_done(struct cmd_q *);
const struct cmd_entry cmd_source_file_entry = {
"source-file", "source",
"", 1, 1,
"path",
0,
cmd_source_file_exec
.name = "source-file",
.alias = "source",
.args = { "", 1, 1 },
.usage = "path",
.flags = 0,
.exec = cmd_source_file_exec
};
enum cmd_retval
@@ -45,8 +48,7 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
struct cmd_q *cmdq1;
char *cause;
cmdq1 = cmdq_new(NULL);
cmdq1->client = cmdq->client;
cmdq1 = cmdq_new(cmdq->client);
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -35,44 +35,46 @@
enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw",
"bc:dF:l:hp:Pt:v", 0, -1,
"[-bdhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_split_window_exec
.name = "split-window",
.alias = "splitw",
.args = { "bc:dF:l:hp:Pt:v", 0, -1 },
.usage = "[-bdhvP] [-c start-directory] [-F format] "
"[-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_split_window_exec
};
enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
const char *cmd, *path, *shell, *template;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp = cmdq->state.tflag.wp, *new_wp = NULL;
struct environ *env;
const char *cmd, *path, *shell, *template, *cwd, *to_free;
char **argv, *cause, *new_cause, *cp;
u_int hlimit;
int argc, size, percentage, cwd, fd = -1;
int argc, size, percentage;
enum layout_type type;
struct layout_cell *lc;
struct format_tree *ft;
struct environ_entry *envent;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
server_unzoom_window(w);
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
env = environ_create();
environ_copy(global_environ, env);
environ_copy(s->environ, env);
server_fill_environ(s, env);
if (args->argc == 0) {
cmd = options_get_string(&s->options, "default-command");
cmd = options_get_string(s->options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
argv = (char **)&cmd;
@@ -85,24 +87,12 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
argv = args->argv;
}
to_free = NULL;
if (args_has(args, 'c')) {
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, NULL,
NULL);
cp = format_expand(ft, args_get(args, 'c'));
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, s, NULL, NULL);
to_free = cwd = format_expand(ft, args_get(args, 'c'));
format_free(ft);
if (cp != NULL && *cp != '\0') {
fd = open(cp, O_RDONLY|O_DIRECTORY);
free(cp);
if (fd == -1) {
cmdq_error(cmdq, "bad working directory: %s",
strerror(errno));
return (CMD_RETURN_ERROR);
}
} else if (cp != NULL)
free(cp);
cwd = fd;
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
@@ -134,9 +124,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
else
size = (wp->sx * percentage) / 100;
}
hlimit = options_get_number(&s->options, "history-limit");
hlimit = options_get_number(s->options, "history-limit");
shell = options_get_string(&s->options, "default-shell");
shell = options_get_string(s->options, "default-shell");
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
@@ -150,13 +140,13 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(&cmdq->client->environ, "PATH");
envent = environ_find(cmdq->client->environ, "PATH");
else
envent = environ_find(&s->environ, "PATH");
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, env,
s->tio, &cause) != 0)
goto error;
@@ -169,15 +159,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
} else
server_status_session(s);
environ_free(&env);
environ_free(env);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = SPLIT_WINDOW_TEMPLATE;
ft = format_create();
format_defaults(ft, cmd_find_client(cmdq, NULL, 1), s, wl,
new_wp);
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, s, wl, new_wp);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
@@ -187,19 +176,20 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
}
notify_window_layout_changed(w);
if (fd != -1)
close(fd);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_NORMAL);
error:
environ_free(&env);
environ_free(env);
if (new_wp != NULL) {
layout_close_pane(new_wp);
window_remove_pane(w, new_wp);
}
cmdq_error(cmdq, "create pane failed: %s", cause);
free(cause);
if (fd != -1)
close(fd);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_ERROR);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -126,7 +126,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
whitespace = argv[0] + strcspn(argv[0], " \t");
if (equals == NULL || equals > whitespace)
break;
environ_put(&global_environ, argv[0]);
environ_put(global_environ, argv[0]);
argc--;
memmove(argv, argv + 1, argc * (sizeof *argv));
}
@@ -303,7 +303,7 @@ cmd_string_variable(const char *s, size_t *p)
buf = xrealloc(buf, len + 1);
buf[len] = '\0';
envent = environ_find(&global_environ, buf);
envent = environ_find(global_environ, buf);
free(buf);
if (envent == NULL)
return (xstrdup(""));
@@ -326,7 +326,7 @@ cmd_string_expand_tilde(const char *s, size_t *p)
last = cmd_string_getc(s, p);
if (last == EOF || last == '/' || last == ' '|| last == '\t') {
envent = environ_find(&global_environ, "HOME");
envent = environ_find(global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
home = envent->value;
else if ((pw = getpwuid(getuid())) != NULL)

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,52 +29,43 @@
enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp",
"dDs:t:U", 0, 0,
"[-dDU] " CMD_SRCDST_PANE_USAGE,
0,
cmd_swap_pane_exec
.name = "swap-pane",
.alias = "swapp",
.args = { "dDs:t:U", 0, 0 },
.usage = "[-dDU] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE_MARKED,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_swap_pane_exec
};
enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *src_wl, *dst_wl;
struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp;
struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;
dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &dst_wp);
if (dst_wl == NULL)
return (CMD_RETURN_ERROR);
dst_w = dst_wl->window;
dst_w = cmdq->state.tflag.wl->window;
dst_wp = cmdq->state.tflag.wp;
src_w = cmdq->state.sflag.wl->window;
src_wp = cmdq->state.sflag.wp;
server_unzoom_window(dst_w);
if (!args_has(args, 's')) {
if (args_has(self->args, 'D')) {
src_w = dst_w;
if (args_has(self->args, 'D')) {
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (args_has(self->args, 'U')) {
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else {
src_wl = cmd_find_pane_marked(cmdq, NULL, NULL,
&src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
src_w = src_wl->window;
}
} else {
src_wl = cmd_find_pane_marked(cmdq, args_get(args, 's'), NULL,
&src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
src_w = src_wl->window;
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (args_has(self->args, 'U')) {
src_w = dst_w;
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
}
server_unzoom_window(src_w);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -29,34 +29,37 @@
enum cmd_retval cmd_swap_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw",
"ds:t:", 0, 0,
"[-d] " CMD_SRCDST_WINDOW_USAGE,
0,
cmd_swap_window_exec
.name = "swap-window",
.alias = "swapw",
.args = { "ds:t:", 0, 0 },
.usage = "[-d] " CMD_SRCDST_WINDOW_USAGE,
.sflag = CMD_WINDOW_MARKED,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_swap_window_exec
};
enum cmd_retval
cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
const char *target_src, *target_dst;
struct session *src, *dst;
struct session_group *sg_src, *sg_dst;
struct winlink *wl_src, *wl_dst;
struct window *w;
target_src = args_get(args, 's');
if ((wl_src = cmd_find_window_marked(cmdq, target_src, &src)) == NULL)
return (CMD_RETURN_ERROR);
target_dst = args_get(args, 't');
if ((wl_dst = cmd_find_window(cmdq, target_dst, &dst)) == NULL)
return (CMD_RETURN_ERROR);
wl_src = cmdq->state.sflag.wl;
src = cmdq->state.sflag.s;
sg_src = session_group_find(src);
wl_dst = cmdq->state.tflag.wl;
dst = cmdq->state.tflag.s;
sg_dst = session_group_find(dst);
if (src != dst &&
sg_src != NULL && sg_dst != NULL && sg_src == sg_dst) {
if (src != dst && sg_src != NULL && sg_dst != NULL &&
sg_src == sg_dst) {
cmdq_error(cmdq, "can't move window, sessions are grouped");
return (CMD_RETURN_ERROR);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -30,34 +30,33 @@
enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc",
"lc:Enpt:rT:", 0, 0,
"[-Elnpr] [-c target-client] [-t target-session] [-T key-table]",
CMD_READONLY,
cmd_switch_client_exec
.name = "switch-client",
.alias = "switchc",
.args = { "lc:Enpt:rT:", 0, 0 },
.usage = "[-Elnpr] [-c target-client] [-t target-session] "
"[-T key-table]",
.cflag = CMD_CLIENT,
.tflag = CMD_SESSION_WITHPANE,
.flags = CMD_READONLY,
.exec = cmd_switch_client_exec
};
enum cmd_retval
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
struct window *w = NULL;
struct window_pane *wp = NULL;
const char *tflag, *tablename, *update;
struct cmd_state *state = &cmdq->state;
struct client *c = state->c;
struct session *s = cmdq->state.tflag.s;
struct window_pane *wp;
const char *tablename, *update;
struct key_table *table;
if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'r')) {
if (c->flags & CLIENT_READONLY)
c->flags &= ~CLIENT_READONLY;
else
c->flags |= CLIENT_READONLY;
}
if (args_has(args, 'r'))
c->flags ^= CLIENT_READONLY;
tablename = args_get(args, 'T');
if (tablename != NULL) {
@@ -69,9 +68,9 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
table->references++;
key_bindings_unref_table(c->keytable);
c->keytable = table;
return (CMD_RETURN_NORMAL);
}
tflag = args_get(args, 't');
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
cmdq_error(cmdq, "can't find next session");
@@ -85,48 +84,32 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
} else if (args_has(args, 'l')) {
if (c->last_session != NULL && session_alive(c->last_session))
s = c->last_session;
else
s = NULL;
if (s == NULL) {
cmdq_error(cmdq, "can't find last session");
return (CMD_RETURN_ERROR);
}
} else {
if (tflag == NULL) {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
} else if (tflag[strcspn(tflag, ":.")] != '\0') {
if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
} else {
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
w = window_find_by_id_str(tflag);
if (w == NULL) {
wp = window_pane_find_by_id_str(tflag);
if (wp != NULL)
w = wp->window;
}
if (w != NULL)
wl = winlink_find_by_window(&s->windows, w);
}
if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL);
if (wl != NULL) {
if (state->tflag.wl != NULL) {
wp = state->tflag.wp;
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, wl);
session_set_current(s, state->tflag.wl);
}
}
if (c != NULL && !args_has(args, 'E')) {
update = options_get_string(&s->options, "update-environment");
environ_update(update, &c->environ, &s->environ);
update = options_get_string(s->options, "update-environment");
environ_update(update, c->environ, s->environ);
}
if (c->session != NULL && c->session != s)
c->last_session = c->session;
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
@@ -135,6 +118,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
server_check_unattached();
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
alerts_check_session(s);
return (CMD_RETURN_NORMAL);
}

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -26,22 +26,26 @@
* Unbind key from command.
*/
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *, int);
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *,
key_code);
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
"acnt:T:", 0, 1,
"[-acn] [-t mode-table] [-T key-table] key",
0,
cmd_unbind_key_exec
.name = "unbind-key",
.alias = "unbind",
.args = { "acnt:T:", 0, 1 },
.usage = "[-acn] [-t mode-table] [-T key-table] key",
.flags = 0,
.exec = cmd_unbind_key_exec
};
enum cmd_retval
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
int key;
key_code key;
const char *tablename;
if (!args_has(args, 'a')) {
@@ -50,7 +54,7 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
@@ -59,13 +63,13 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "key given with -a");
return (CMD_RETURN_ERROR);
}
key = KEYC_NONE;
key = KEYC_UNKNOWN;
}
if (args_has(args, 't'))
return (cmd_unbind_key_mode_table(self, cmdq, key));
if (key == KEYC_NONE) {
if (key == KEYC_UNKNOWN) {
tablename = args_get(args, 'T');
if (tablename == NULL) {
key_bindings_remove_table("root");
@@ -95,7 +99,7 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
{
struct args *args = self->args;
const char *tablename;
@@ -108,7 +112,7 @@ cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, int key)
return (CMD_RETURN_ERROR);
}
if (key == KEYC_NONE) {
if (key == KEYC_UNKNOWN) {
while (!RB_EMPTY(mtab->tree)) {
mbind = RB_ROOT(mtab->tree);
RB_REMOVE(mode_key_tree, mtab->tree, mbind);

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
* Copyright (c) 2013 Thiago de Arruda <tpadilha84@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -31,11 +31,14 @@
enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_wait_for_entry = {
"wait-for", "wait",
"LSU", 1, 1,
"[-L|-S|-U] channel",
0,
cmd_wait_for_exec
.name = "wait-for",
.alias = "wait",
.args = { "LSU", 1, 1 },
.usage = "[-L|-S|-U] channel",
.flags = 0,
.exec = cmd_wait_for_exec
};
struct wait_channel {
@@ -111,7 +114,7 @@ cmd_wait_for_remove(struct wait_channel *wc)
}
enum cmd_retval
cmd_wait_for_exec(struct cmd *self, unused struct cmd_q *cmdq)
cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
const char *name = args->argv[0];
@@ -130,7 +133,7 @@ cmd_wait_for_exec(struct cmd *self, unused struct cmd_q *cmdq)
}
enum cmd_retval
cmd_wait_for_signal(unused struct cmd_q *cmdq, const char *name,
cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
struct cmd_q *wq, *wq1;
@@ -170,12 +173,11 @@ cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
wc = cmd_wait_for_add(name);
if (wc->woken) {
log_debug("wait channel %s already woken (client %d)", wc->name,
c->tty.fd);
log_debug("wait channel %s already woken (%p)", wc->name, c);
cmd_wait_for_remove(wc);
return (CMD_RETURN_NORMAL);
}
log_debug("wait channel %s not woken (client %d)", wc->name, c->tty.fd);
log_debug("wait channel %s not woken (%p)", wc->name, c);
TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry);
cmdq->references++;

205
cmd.c
View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -95,10 +95,12 @@ extern const struct cmd_entry cmd_send_prefix_entry;
extern const struct cmd_entry cmd_server_info_entry;
extern const struct cmd_entry cmd_set_buffer_entry;
extern const struct cmd_entry cmd_set_environment_entry;
extern const struct cmd_entry cmd_set_hook_entry;
extern const struct cmd_entry cmd_set_option_entry;
extern const struct cmd_entry cmd_set_window_option_entry;
extern const struct cmd_entry cmd_show_buffer_entry;
extern const struct cmd_entry cmd_show_environment_entry;
extern const struct cmd_entry cmd_show_hooks_entry;
extern const struct cmd_entry cmd_show_messages_entry;
extern const struct cmd_entry cmd_show_options_entry;
extern const struct cmd_entry cmd_show_window_options_entry;
@@ -182,10 +184,12 @@ const struct cmd_entry *cmd_table[] = {
&cmd_server_info_entry,
&cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_hook_entry,
&cmd_set_option_entry,
&cmd_set_window_option_entry,
&cmd_show_buffer_entry,
&cmd_show_environment_entry,
&cmd_show_hooks_entry,
&cmd_show_messages_entry,
&cmd_show_options_entry,
&cmd_show_window_options_entry,
@@ -344,12 +348,12 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
return (NULL);
}
args = args_parse(entry->args_template, argc, argv);
args = args_parse(entry->args.template, argc, argv);
if (args == NULL)
goto usage;
if (entry->args_lower != -1 && args->argc < entry->args_lower)
if (entry->args.lower != -1 && args->argc < entry->args.lower)
goto usage;
if (entry->args_upper != -1 && args->argc > entry->args_upper)
if (entry->args.upper != -1 && args->argc > entry->args.upper)
goto usage;
cmd = xcalloc(1, sizeof *cmd);
@@ -383,21 +387,192 @@ usage:
return (NULL);
}
size_t
cmd_print(struct cmd *cmd, char *buf, size_t len)
static int
cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
struct cmd_q *cmdq, struct cmd_q *parent)
{
size_t off, used;
int targetflags, error;
struct cmd_find_state *fs = NULL;
struct cmd_find_state *current = NULL;
struct cmd_find_state tmp;
off = xsnprintf(buf, len, "%s ", cmd->entry->name);
if (off + 1 < len) {
used = args_print(cmd->args, buf + off, len - off - 1);
if (used == 0)
off--;
if (flag == CMD_NONE ||
flag == CMD_CLIENT ||
flag == CMD_CLIENT_CANFAIL)
return (0);
if (c == 't')
fs = &cmdq->state.tflag;
else if (c == 's')
fs = &cmdq->state.sflag;
if (flag == CMD_SESSION_WITHPANE) {
if (target != NULL && target[strcspn(target, ":.")] != '\0')
flag = CMD_PANE;
else
off += used;
buf[off] = '\0';
flag = CMD_SESSION;
}
return (off);
targetflags = 0;
switch (flag) {
case CMD_SESSION:
case CMD_SESSION_CANFAIL:
case CMD_SESSION_PREFERUNATTACHED:
if (flag == CMD_SESSION_CANFAIL)
targetflags |= CMD_FIND_QUIET;
if (flag == CMD_SESSION_PREFERUNATTACHED)
targetflags |= CMD_FIND_PREFER_UNATTACHED;
break;
case CMD_MOVEW_R:
flag = CMD_WINDOW_INDEX;
/* FALLTHROUGH */
case CMD_WINDOW:
case CMD_WINDOW_CANFAIL:
case CMD_WINDOW_MARKED:
case CMD_WINDOW_INDEX:
if (flag == CMD_WINDOW_CANFAIL)
targetflags |= CMD_FIND_QUIET;
if (flag == CMD_WINDOW_MARKED)
targetflags |= CMD_FIND_DEFAULT_MARKED;
if (flag == CMD_WINDOW_INDEX)
targetflags |= CMD_FIND_WINDOW_INDEX;
break;
case CMD_PANE:
case CMD_PANE_CANFAIL:
case CMD_PANE_MARKED:
if (flag == CMD_PANE_CANFAIL)
targetflags |= CMD_FIND_QUIET;
if (flag == CMD_PANE_MARKED)
targetflags |= CMD_FIND_DEFAULT_MARKED;
break;
default:
fatalx("unknown %cflag %d", c, flag);
}
log_debug("%s: flag %c %d %#x", __func__, c, flag, targetflags);
if (parent != NULL) {
if (c == 't')
current = &parent->state.tflag;
else if (c == 's')
current = &parent->state.sflag;
} else {
error = cmd_find_current(&tmp, cmdq, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
current = &tmp;
}
switch (flag) {
case CMD_NONE:
case CMD_CLIENT:
case CMD_CLIENT_CANFAIL:
return (0);
case CMD_SESSION:
case CMD_SESSION_CANFAIL:
case CMD_SESSION_PREFERUNATTACHED:
case CMD_SESSION_WITHPANE:
error = cmd_find_target(fs, current, cmdq, target,
CMD_FIND_SESSION, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
break;
case CMD_MOVEW_R:
error = cmd_find_target(fs, current, cmdq, target,
CMD_FIND_SESSION, CMD_FIND_QUIET);
if (error == 0)
break;
/* FALLTHROUGH */
case CMD_WINDOW:
case CMD_WINDOW_CANFAIL:
case CMD_WINDOW_MARKED:
case CMD_WINDOW_INDEX:
error = cmd_find_target(fs, current, cmdq, target,
CMD_FIND_WINDOW, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
break;
case CMD_PANE:
case CMD_PANE_CANFAIL:
case CMD_PANE_MARKED:
error = cmd_find_target(fs, current, cmdq, target,
CMD_FIND_PANE, targetflags);
if (error != 0 && ~targetflags & CMD_FIND_QUIET)
return (-1);
break;
default:
fatalx("unknown %cflag %d", c, flag);
}
return (0);
}
int
cmd_prepare_state(struct cmd *cmd, struct cmd_q *cmdq, struct cmd_q *parent)
{
const struct cmd_entry *entry = cmd->entry;
struct cmd_state *state = &cmdq->state;
char *tmp;
enum cmd_entry_flag flag;
const char *s;
int error;
tmp = cmd_print(cmd);
log_debug("preparing state for %s (client %p)", tmp, cmdq->client);
free(tmp);
state->c = NULL;
cmd_find_clear_state(&state->tflag, NULL, 0);
cmd_find_clear_state(&state->sflag, NULL, 0);
flag = cmd->entry->cflag;
if (flag == CMD_NONE) {
flag = cmd->entry->tflag;
if (flag == CMD_CLIENT || flag == CMD_CLIENT_CANFAIL)
s = args_get(cmd->args, 't');
else
s = NULL;
} else
s = args_get(cmd->args, 'c');
switch (flag) {
case CMD_CLIENT:
state->c = cmd_find_client(cmdq, s, 0);
if (state->c == NULL)
return (-1);
break;
default:
state->c = cmd_find_client(cmdq, s, 1);
break;
}
s = args_get(cmd->args, 't');
log_debug("preparing -t state: target %s", s == NULL ? "none" : s);
error = cmd_prepare_state_flag('t', s, entry->tflag, cmdq, parent);
if (error != 0)
return (error);
s = args_get(cmd->args, 's');
log_debug("preparing -s state: target %s", s == NULL ? "none" : s);
error = cmd_prepare_state_flag('s', s, entry->sflag, cmdq, parent);
if (error != 0)
return (error);
return (0);
}
char *
cmd_print(struct cmd *cmd)
{
char *out, *s;
s = args_print(cmd->args);
if (*s != '\0')
xasprintf(&out, "%s %s", cmd->entry->name, s);
else
out = xstrdup(cmd->entry->name);
free(s);
return (out);
}
/* Adjust current mouse position for a pane. */

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -21,6 +21,9 @@
#define __attribute__(a)
#endif
#ifndef __unused
#define __unused __attribute__ ((__unused__))
#endif
#ifndef __dead
#define __dead __attribute__ ((__noreturn__))
#endif
@@ -255,13 +258,18 @@ int unsetenv(const char *);
#ifndef HAVE_CFMAKERAW
/* cfmakeraw.c */
void cfmakeraw(struct termios *);
void cfmakeraw(struct termios *);
#endif
#ifndef HAVE_OPENAT
/* openat.c */
#define AT_FDCWD -100
int openat(int, const char *, int, ...);
int openat(int, const char *, int, ...);
#endif
#ifndef HAVE_REALLOCARRAY
/* reallocarray.c */
void *reallocarray(void *, size_t, size_t size);
#endif
#ifdef HAVE_GETOPT

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2006 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013 Dagobert Michelsen
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -14,8 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "tmux.h"
#ifndef HAVE_CLOSEFROM
#include <sys/types.h>
@@ -47,6 +45,8 @@
# endif
#endif
#include "tmux.h"
#ifndef OPEN_MAX
# define OPEN_MAX 256
#endif

View File

@@ -1,43 +1,26 @@
/* $NetBSD: fgetln.c,v 1.3 2007/08/07 02:06:58 lukem Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
/*
* Copyright (c) 2015 Joerg Jung <jung@openbsd.org>
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
* 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.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 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/types.h>
/*
* portable fgetln() version, NOT reentrant
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "tmux.h"
@@ -45,41 +28,34 @@ char *
fgetln(FILE *fp, size_t *len)
{
static char *buf = NULL;
static size_t bufsiz = 0;
char *ptr;
static size_t bufsz = 0;
size_t r = 0;
char *p;
int c, e;
if (buf == NULL) {
bufsiz = BUFSIZ;
if ((buf = malloc(bufsiz)) == NULL)
return NULL;
}
if (fgets(buf, bufsiz, fp) == NULL)
if (!fp || !len) {
errno = EINVAL;
return NULL;
*len = 0;
while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
size_t nbufsiz = bufsiz + BUFSIZ;
char *nbuf = realloc(buf, nbufsiz);
if (nbuf == NULL) {
int oerrno = errno;
free(buf);
errno = oerrno;
buf = NULL;
return NULL;
} else
buf = nbuf;
*len = bufsiz;
if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL)
return buf;
bufsiz = nbufsiz;
}
*len = (ptr - buf) + 1;
return buf;
if (!buf) {
if (!(buf = calloc(1, BUFSIZ)))
return NULL;
bufsz = BUFSIZ;
}
while ((c = getc(fp)) != EOF) {
buf[r++] = c;
if (r == bufsz) {
if (!(p = reallocarray(buf, 2, bufsz))) {
e = errno;
free(buf);
errno = e;
buf = NULL, bufsz = 0;
return NULL;
}
buf = p, bufsz = 2 * bufsz;
}
if (c == '\n')
break;
}
return (*len = r) ? buf : NULL;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

40
compat/reallocarray.c Normal file
View File

@@ -0,0 +1,40 @@
/* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.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 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 <stdint.h>
#include <stdlib.h>
#include "tmux.h"
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2010 Dagobert Michelsen
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above

View File

@@ -73,9 +73,6 @@
*/
#define UNVIS_END 1 /* no more characters */
#include <sys/cdefs.h>
__BEGIN_DECLS
char *vis(char *, int, int, int);
int strvis(char *, const char *, int);
int stravis(char **, const char *, int);
@@ -85,6 +82,4 @@ int strunvis(char *, const char *);
int unvis(char *, char, int *, int);
ssize_t strnunvis(char *, const char *, size_t);
__END_DECLS
#endif /* !_VIS_H_ */

View File

@@ -1,7 +1,6 @@
# configure.ac
# Miscellaneous bits.
AC_INIT(tmux, 2.1)
AC_INIT(tmux, 2.2)
AC_CONFIG_AUX_DIR(etc)
AM_INIT_AUTOMAKE([foreign subdir-objects])
@@ -19,6 +18,7 @@ AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
PKG_PROG_PKG_CONFIG
# Default tmux.conf goes in /etc not ${prefix}/etc.
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
@@ -48,6 +48,7 @@ AC_ARG_ENABLE(
)
if test "x$found_static" = xyes; then
LDFLAGS="$LDFLAGS -static"
PKG_CONFIG="pkg-config --static"
fi
# Is this gcc?
@@ -143,22 +144,48 @@ if test "x$found_libevent" = xno; then
AC_MSG_ERROR("libevent not found")
fi
# Look for curses.
AC_SEARCH_LIBS(
setupterm,
[terminfo curses ncurses tinfo],
found_curses=yes,
found_curses=no
# Look for ncurses
PKG_CHECK_MODULES(
LIBNCURSES,
ncurses,
[
CPPFLAGS="$LIBNCURSES_CFLAGS $CPPFLAGS"
LIBS="$LIBNCURSES_LIBS $LIBS"
found_curses=yes
],
[
AC_SEARCH_LIBS(
setupterm,
[ncurses curses terminfo],
found_curses=yes,
found_curses=no
)
]
)
if test "x$found_curses" = xno; then
AC_MSG_ERROR("curses not found")
fi
# Look for utempter.
AC_CHECK_HEADER(utempter.h, have_utempter=yes, have_utempter=no)
if test "x$have_utempter" = xyes; then
AC_DEFINE(HAVE_UTEMPTER)
LIBS="$LIBS -lutempter"
AC_ARG_ENABLE(
utempter,
AC_HELP_STRING(--enable-utempter, use utempter if it is installed),
found_utempter=$enable_utempter,
found_utempter=yes
)
if test "x$found_utempter" = xyes; then
AC_CHECK_HEADER(utempter.h, found_utempter=yes, found_utempter=no)
if test "x$found_utempter" = xyes; then
AC_SEARCH_LIBS(
utempter_add_record,
utempter,
found_utempter=yes,
found_utempter=no
)
if test "x$found_utempter" = xyes; then
AC_DEFINE(HAVE_UTEMPTER)
fi
fi
fi
# Check for b64_ntop.
@@ -365,6 +392,13 @@ if test "x$found_openat" = xyes; then
fi
AM_CONDITIONAL(NO_OPENAT, [test "x$found_openat" = xno])
# Look for reallocarray, compat/reallocarray.c used if missing.
AC_CHECK_FUNC(reallocarray, found_reallocarray=yes, found_reallocarray=no)
if test "x$found_reallocarray" = xyes; then
AC_DEFINE(HAVE_REALLOCARRAY)
fi
AM_CONDITIONAL(NO_REALLOCARRAY, [test "x$found_reallocarray" = xno])
# Look for getopt. glibc's getopt does not enforce argument order and the ways
# of making it do so are stupid, so just use our own instead.
AC_CHECK_FUNC(getopt, found_getopt=yes, found_getopt=no)

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -19,6 +19,8 @@
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
@@ -65,6 +67,10 @@ control_notify_window_layout_changed(struct window *w)
struct format_tree *ft;
struct winlink *wl;
const char *template;
char *expanded;
template = "%layout-change #{window_id} #{window_layout} "
"#{window_visible_layout} #{window_flags}";
TAILQ_FOREACH(c, &clients, entry) {
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
@@ -81,20 +87,21 @@ control_notify_window_layout_changed(struct window *w)
*/
if (w->layout_root == NULL)
continue;
template = "%layout-change #{window_id} #{window_layout}";
ft = format_create();
ft = format_create(NULL, 0);
wl = winlink_find_by_window(&s->windows, w);
if (wl != NULL) {
format_defaults(ft, c, NULL, wl, NULL);
control_write(c, "%s", format_expand(ft, template));
expanded = format_expand(ft, template);
control_write(c, "%s", expanded);
free(expanded);
}
format_free(ft);
}
}
void
control_notify_window_unlinked(unused struct session *s, struct window *w)
control_notify_window_unlinked(__unused struct session *s, struct window *w)
{
struct client *c;
struct session *cs;
@@ -112,7 +119,7 @@ control_notify_window_unlinked(unused struct session *s, struct window *w)
}
void
control_notify_window_linked(unused struct session *s, struct window *w)
control_notify_window_linked(__unused struct session *s, struct window *w)
{
struct client *c;
struct session *cs;
@@ -176,7 +183,7 @@ control_notify_session_renamed(struct session *s)
}
void
control_notify_session_created(unused struct session *s)
control_notify_session_created(__unused struct session *s)
{
struct client *c;
@@ -189,7 +196,7 @@ control_notify_session_created(unused struct session *s)
}
void
control_notify_session_close(unused struct session *s)
control_notify_session_close(__unused struct session *s)
{
struct client *c;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -37,7 +37,7 @@ control_write(struct client *c, const char *fmt, ...)
va_end(ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
server_client_push_stdout(c);
}
/* Write a buffer, adding a terminal newline. Empties buffer. */
@@ -46,12 +46,12 @@ control_write_buffer(struct client *c, struct evbuffer *buffer)
{
evbuffer_add_buffer(c->stdout_data, buffer);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
server_client_push_stdout(c);
}
/* Control input callback. Read lines and fire commands. */
void
control_callback(struct client *c, int closed, unused void *data)
control_callback(struct client *c, int closed, __unused void *data)
{
char *line, *cause;
struct cmd_list *cmdlist;

View File

@@ -1,7 +1,7 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -27,6 +27,9 @@
* Environment - manipulate a set of environment variables.
*/
RB_HEAD(environ, environ_entry);
int environ_cmp(struct environ_entry *, struct environ_entry *);
RB_PROTOTYPE(environ, environ_entry, entry, environ_cmp);
RB_GENERATE(environ, environ_entry, entry, environ_cmp);
int
@@ -36,25 +39,42 @@ environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
}
/* Initialise the environment. */
void
environ_init(struct environ *env)
struct environ *
environ_create(void)
{
struct environ *env;
env = xcalloc(1, sizeof *env);
RB_INIT(env);
return (env);
}
/* Free an environment. */
void
environ_free(struct environ *env)
{
struct environ_entry *envent;
struct environ_entry *envent, *envent1;
while (!RB_EMPTY(env)) {
envent = RB_ROOT(env);
RB_FOREACH_SAFE(envent, environ, env, envent1) {
RB_REMOVE(environ, env, envent);
free(envent->name);
free(envent->value);
free(envent);
}
free(env);
}
struct environ_entry *
environ_first(struct environ *env)
{
return (RB_MIN(environ, env));
}
struct environ_entry *
environ_next(struct environ_entry *envent)
{
return (RB_NEXT(environ, env, envent));
}
/* Copy one environment into another. */
@@ -63,8 +83,12 @@ environ_copy(struct environ *srcenv, struct environ *dstenv)
{
struct environ_entry *envent;
RB_FOREACH(envent, environ, srcenv)
environ_set(dstenv, envent->name, envent->value);
RB_FOREACH(envent, environ, srcenv) {
if (envent->value == NULL)
environ_clear(dstenv, envent->name);
else
environ_set(dstenv, envent->name, "%s", envent->value);
}
}
/* Find an environment variable. */
@@ -79,23 +103,37 @@ environ_find(struct environ *env, const char *name)
/* Set an environment variable. */
void
environ_set(struct environ *env, const char *name, const char *value)
environ_set(struct environ *env, const char *name, const char *fmt, ...)
{
struct environ_entry *envent;
va_list ap;
va_start(ap, fmt);
if ((envent = environ_find(env, name)) != NULL) {
free(envent->value);
xvasprintf(&envent->value, fmt, ap);
} else {
envent = xmalloc(sizeof *envent);
envent->name = xstrdup(name);
xvasprintf(&envent->value, fmt, ap);
RB_INSERT(environ, env, envent);
}
va_end(ap);
}
/* Clear an environment variable. */
void
environ_clear(struct environ *env, const char *name)
{
struct environ_entry *envent;
if ((envent = environ_find(env, name)) != NULL) {
free(envent->value);
if (value != NULL)
envent->value = xstrdup(value);
else
envent->value = NULL;
envent->value = NULL;
} else {
envent = xmalloc(sizeof *envent);
envent->name = xstrdup(name);
if (value != NULL)
envent->value = xstrdup(value);
else
envent->value = NULL;
envent->value = NULL;
RB_INSERT(environ, env, envent);
}
}
@@ -114,7 +152,7 @@ environ_put(struct environ *env, const char *var)
name = xstrdup(var);
name[strcspn(name, "=")] = '\0';
environ_set(env, name, value);
environ_set(env, name, "%s", value);
free(name);
}
@@ -146,9 +184,9 @@ environ_update(const char *vars, struct environ *srcenv,
copyvars = next = xstrdup(vars);
while ((var = strsep(&next, " ")) != NULL) {
if ((envent = environ_find(srcenv, var)) == NULL)
environ_set(dstenv, var, NULL);
environ_clear(dstenv, var);
else
environ_set(dstenv, envent->name, envent->value);
environ_set(dstenv, envent->name, "%s", envent->value);
}
free(copyvars);
}
@@ -158,10 +196,10 @@ void
environ_push(struct environ *env)
{
struct environ_entry *envent;
char **vp, *v;
char *v;
for (vp = environ; *vp != NULL; vp++) {
v = xstrdup(*vp);
while (*environ != NULL) {
v = xstrdup(*environ);
v[strcspn(v, "=")] = '\0';
unsetenv(v);

66
example_tmux.conf Normal file
View File

@@ -0,0 +1,66 @@
#
# Example .tmux.conf
#
# By Nicholas Marriott. Public domain.
#
# Some tweaks to the status line
set -g status-bg green
set -g status-right "%H:%M"
set -g window-status-current-attr "underscore"
# No bells at all
set -g bell-action none
# Lock after 15 minutes
set -g lock-after-time 1800
# Keep windows around after they exit
set -g remain-on-exit on
# Turn on xterm-keys so that additional function keys get escape sequences
set -g xterm-keys on
# Change the prefix key to C-a
set -g prefix C-a
unbind C-b
bind C-a send-prefix
# Turn the mouse on, but without copy mode dragging
set -g mouse on
unbind -n MouseDrag1Pane
unbind -temacs-copy MouseDrag1Pane
# Some extra key bindings to select higher numbered windows
bind F1 selectw -t:10
bind F2 selectw -t:11
bind F3 selectw -t:12
bind F4 selectw -t:13
bind F5 selectw -t:14
bind F6 selectw -t:15
bind F7 selectw -t:16
bind F8 selectw -t:17
bind F9 selectw -t:18
bind F10 selectw -t:19
bind F11 selectw -t:20
bind F12 selectw -t:21
# Keys to toggle monitoring activity in a window, and synchronize-panes
bind m set monitor-activity
bind y set synchronize-panes\; display 'synchronize-panes #{?synchronize-panes,on,off}'
# Keys to hide and show a window name from the status line
bind '-' set window-status-format '#I'\; set window-status-current-format '#I'
bind '+' set window-status-format '#I:#W#F'\; set window-status-current-format '#I:#W#F'
# Create a single default session
new -d -s0 -nirssi 'exec irssi'
set -t0:0 monitor-activity on
set -t0:0 aggressive-resize on
neww -d -ntodo 'exec emacs ~/TODO'
setw -t0:1 aggressive-resize on
neww -d -nmutt 'exec mutt'
setw -t0:2 aggressive-resize on
neww -d
neww -d
neww -d

View File

@@ -1,105 +0,0 @@
# START tmux completion
# This file is in the public domain
# See: http://www.debian-administration.org/articles/317 for how to write more.
# Usage: Put "source bash_completion_tmux.sh" into your .bashrc
_tmux()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts=" \
attach-session \
bind-key \
break-pane \
capture-pane \
choose-client \
choose-session \
choose-window \
clear-history \
clock-mode \
command-prompt \
confirm-before \
copy-buffer \
copy-mode \
delete-buffer \
detach-client \
display-message \
display-panes \
down-pane \
find-window \
has-session \
if-shell \
join-pane \
kill-pane \
kill-server \
kill-session \
kill-window \
last-window \
link-window \
list-buffers \
list-clients \
list-commands \
list-keys \
list-panes \
list-sessions \
list-windows \
load-buffer \
lock-client \
lock-server \
lock-session \
move-window \
new-session \
new-window \
next-layout \
next-window \
paste-buffer \
pipe-pane \
previous-layout \
previous-window \
refresh-client \
rename-session \
rename-window \
resize-pane \
respawn-window \
rotate-window \
run-shell \
save-buffer \
select-layout \
select-pane \
select-prompt \
select-window \
send-keys \
send-prefix \
server-info \
set-buffer \
set-environment \
set-option \
set-window-option \
show-buffer \
show-environment \
show-messages \
show-options \
show-window-options \
source-file \
split-window \
start-server \
suspend-client \
swap-pane \
swap-window \
switch-client \
unbind-key \
unlink-window \
up-pane"
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
}
complete -F _tmux tmux
# END tmux completion

View File

@@ -1,42 +0,0 @@
# $Id: h-boetes.conf,v 1.2 2009-10-25 21:45:26 nicm Exp $
#
# From Han Boetes.
set -g default-command zsh
set -g status-right "#(uptime|awk '{print $11}') #(date)"
# Statusbar properties.
set -g display-time 3000
set -g status-bg black
set -g status-fg cyan
set-window-option -g window-status-current-attr bright,reverse
set-window-option -g window-status-current-bg cyan
set-window-option -g window-status-current-fg black
# Use c-t instead of c-b as the prefix
unbind C-b
set -g prefix C-t
bind C-t send-prefix
bind t send-prefix
# Bind function keys.
bind -n F1 select-window -t 1
bind -n F2 select-window -t 2
bind -n F3 select-window -t 3
bind -n F4 select-window -t 4
bind -n F5 select-window -t 5
bind -n F6 select-window -t 6
bind -n F7 select-window -t 7
bind -n F8 select-window -t 8
# All new windows started at startup.
new emacs
neww irssi
neww mutt
neww
neww
neww
neww
neww
select-window -t 1

View File

@@ -1,110 +0,0 @@
# $Id: n-marriott.conf,v 1.11 2009-11-24 19:03:59 nicm Exp $
#
# By Nicholas Marriott. Public domain.
# Default global options.
set -g status-bg green
set -g status-right "%H:%M" # %d-%b-%y
set -g bell-action none
set -g lock-after-time 1800
# Default global window options.
setw -g remain-on-exit on
setw -g window-status-current-attr "underscore"
#setw -g xterm-keys on
# Prefix key.
set -g prefix C-a
unbind C-b
bind C-a send-prefix
# Keys to switch session.
bind Q switchc -t0
bind W switchc -t1
bind E switchc -t2
# Other key bindings.
bind F1 selectw -t:10
bind F2 selectw -t:11
bind F3 selectw -t:12
bind F4 selectw -t:13
bind F5 selectw -t:14
bind F6 selectw -t:15
bind F7 selectw -t:16
bind F8 selectw -t:17
bind F9 selectw -t:18
bind F10 selectw -t:19
bind F11 selectw -t:20
bind F12 selectw -t:21
bind m setw monitor-activity
bind y setw force-width 81
bind u setw force-width 0
bind -n F1 run-shell 'mpc toggle >/dev/null 2>&1'
bind -n F2 run-shell 'mpc'
bind -n F3 run-shell 'mpc prev >/dev/null 2>&1'
bind -n F4 run-shell 'mpc next >/dev/null 2>&1'
bind -n F5 run-shell 'mpc volume -5 >/dev/null 2>&1'
bind -n F6 run-shell 'mpc volume +5 >/dev/null 2>&1'
# Hide and show window name from status line
bind '-' setw window-status-format '#I'\; setw window-status-current-format '#I'
bind '+' setw window-status-format '#I:#W#F'\; setw window-status-current-format '#I:#W#F'
# First session.
new -d -s0 -nirssi 'exec ssh -t natalya exec sh ~/bin/tmux-start'
setw -t0:0 monitor-activity on
setw -t0:0 aggressive-resize on
set -t0 status-bg green
neww -d -ntodo 'exec emacs ~/TODO'
setw -t0:1 aggressive-resize on
neww -d -ntodo2 'exec emacs ~/TODO2'
setw -t0:2 aggressive-resize on
neww -d -nncmpc 'exec ncmpc -f ~/.ncmpc.conf'
setw -t0:3 aggressive-resize on
neww -d -nmutt 'exec mutt'
setw -t0:4 aggressive-resize on
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
# Second session.
new -d -s1
set -t1 status-bg cyan
linkw -dk -t0 -s0:0
linkw -dk -t1 -s0:1
linkw -dk -t2 -s0:2
linkw -dk -t3 -s0:3
linkw -dk -t4 -s0:4
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d
# Third session.
new -d -s2
set -t2 status-bg yellow
linkw -dk -t0 -s0:0
linkw -dk -t1 -s0:1
linkw -dk -t2 -s0:2
linkw -dk -t3 -s0:3
linkw -dk -t4 -s0:4
neww -d
neww -d
neww -d
neww -d
neww -d
neww -d

View File

@@ -1,102 +0,0 @@
# $Id: screen-keys.conf,v 1.7 2010-07-31 11:39:13 nicm Exp $
#
# By Nicholas Marriott. Public domain.
#
# This configuration file binds many of the common GNU screen key bindings to
# appropriate tmux key bindings. Note that for some key bindings there is no
# tmux analogue and also that this set omits binding some commands available in
# tmux but not in screen.
#
# Note this is only a selection of key bindings and they are in addition to the
# normal tmux key bindings. This is intended as an example not as to be used
# as-is.
# Set the prefix to ^A.
unbind C-b
set -g prefix ^A
bind a send-prefix
# Bind appropriate commands similar to screen.
# lockscreen ^X x
unbind ^X
bind ^X lock-server
unbind x
bind x lock-server
# screen ^C c
unbind ^C
bind ^C new-window
unbind c
bind c new-window
# detach ^D d
unbind ^D
bind ^D detach
# displays *
unbind *
bind * list-clients
# next ^@ ^N sp n
unbind ^@
bind ^@ next-window
unbind ^N
bind ^N next-window
unbind " "
bind " " next-window
unbind n
bind n next-window
# title A
unbind A
bind A command-prompt "rename-window %%"
# other ^A
unbind ^A
bind ^A last-window
# prev ^H ^P p ^?
unbind ^H
bind ^H previous-window
unbind ^P
bind ^P previous-window
unbind p
bind p previous-window
unbind BSpace
bind BSpace previous-window
# windows ^W w
unbind ^W
bind ^W list-windows
unbind w
bind w list-windows
# quit \
unbind '\'
bind '\' confirm-before "kill-server"
# kill K k
unbind K
bind K confirm-before "kill-window"
unbind k
bind k confirm-before "kill-window"
# redisplay ^L l
unbind ^L
bind ^L refresh-client
unbind l
bind l refresh-client
# split -v |
unbind |
bind | split-window
# :kB: focus up
unbind Tab
bind Tab select-pane -t:.+
unbind BTab
bind BTab select-pane -t:.-
# " windowlist -b
unbind '"'
bind '"' choose-window

View File

@@ -1,104 +0,0 @@
# $Id: t-williams.conf,v 1.1 2009-11-02 18:59:28 nicm Exp $
#
# ~/.tmux.conf - tmux terminal multiplexer config
# Thayer Williams (http://cinderwick.ca)
# "Feel free to do whatever you like with it."
# I typically start tmux from ~/.xinitrc with the following:
#
# urxvt -e bash -c "tmux attach -d -t mysession" &
#
# and recall it any time thereafter with xbindkeys (Mod4+s):
#
# "urxvt -e bash -c 'tmux attach -d -t mysession'"
# m:0x50 + c:39
# set prefix key to ctrl+a until I have time to adapt
unbind C-b
set -g prefix C-a
# send the prefix to client inside window (ala nested sessions)
bind-key a send-prefix
# toggle last window like screen
bind-key C-a last-window
# confirm before killing a window or the server
bind-key k confirm kill-window
bind-key K confirm kill-server
# toggle statusbar
bind-key b set-option status
# ctrl+left/right cycles thru windows
bind-key -n C-right next
bind-key -n C-left prev
# open a man page in new window
bind / command-prompt "split-window 'exec man %%'"
# quick view of processes
bind '~' split-window "exec htop"
# scrollback buffer n lines
set -g history-limit 5000
# listen for activity on all windows
set -g bell-action any
# on-screen time for display-panes in ms
set -g display-panes-time 2000
# start window indexing at one instead of zero
set -g base-index 1
# enable wm window titles
set -g set-titles on
# wm window title string (uses statusbar variables)
set -g set-titles-string "tmux.#I.#W"
# session initialization
new -s mysession mutt
neww -t 2
neww -d -t 3
neww -d -t 5 mocp
neww -d -t 6 rtorrent
selectw -t 1
# statusbar --------------------------------------------------------------
set -g display-time 2000
# default statusbar colors
set -g status-fg white
set -g status-bg default
set -g status-attr default
# default window title colors
set-window-option -g window-status-fg cyan
set-window-option -g window-status-bg default
set-window-option -g window-status-attr dim
# active window title colors
set-window-option -g window-status-current-fg white
set-window-option -g window-status-current-bg default
set-window-option -g window-status-current-attr bright
# command/message line colors
set -g message-fg white
set -g message-bg black
set -g message-attr bright
# center align the window list
set -g status-justify centre
# show some useful stats but only when tmux is started
# outside of Xorg, otherwise dwm statusbar shows these already
set -g status-right ""
set -g status-left ""
if '[ -z "$DISPLAY" ]' 'set -g status-left "[#[fg=green] #H #[default]]"'
if '[ -z "$DISPLAY" ]' 'set -g status-right "[ #[fg=magenta]#(cat /proc/loadavg | cut -d \" \" -f 1,2,3)#[default] ][ #[fg=cyan,bright]%a %Y-%m-%d %H:%M #[default]]"'
if '[ -z "$DISPLAY" ]' 'set -g status-right-length 50'

View File

@@ -1,289 +0,0 @@
" Vim syntax file
" Language: tmux(1) configuration file
" Maintainer: Tiago Cunha <tcunha@users.sourceforge.net>
" Last Change: $Date: 2010-07-27 18:29:07 $
" License: This file is placed in the public domain.
"
" To install this file:
"
" - Drop the file in the syntax directory into runtimepath (such as
" ~/.vim/syntax/tmux.vim).
" - Make the filetype recognisable by adding the following to filetype.vim
" (~/.vim/filetype.vim):
"
" augroup filetypedetect
" au BufNewFile,BufRead .tmux.conf*,tmux.conf* setf tmux
" augroup END
"
" - Switch on syntax highlighting by adding "syntax enable" to .vimrc.
"
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
setlocal iskeyword+=-
syntax case match
syn keyword tmuxAction any current none
syn keyword tmuxBoolean off on
syn keyword tmuxCmds
\ attach[-session]
\ bind[-key]
\ break-pane
\ breakp
\ capture-pane
\ capturep
\ choose-buffer
\ choose-client
\ choose-list
\ choose-session
\ choose-tree
\ choose-window
\ clear-history
\ clearhist
\ clock-mode
\ command-prompt
\ confirm[-before]
\ copy-mode
\ delete-buffer
\ deleteb
\ detach[-client]
\ display[-message]
\ display-panes
\ displayp
\ find-window
\ findw
\ has[-session]
\ if[-shell]
\ join-pane
\ joinp
\ kill-pane
\ killp
\ kill-server
\ kill-session
\ kill-window
\ killw
\ last-pane
\ lastp
\ last[-window]
\ link-window
\ linkw
\ list-buffers
\ lsb
\ list-clients
\ lsc
\ list-commands
\ lscm
\ list-keys
\ lsk
\ list-panes
\ lsp
\ list-sessions
\ ls
\ list-windows
\ lsw
\ load-buffer
\ loadb
\ lock-client
\ lockc
\ lock[-server]
\ lock-session
\ locks
\ move-pane
\ movep
\ move-window
\ movew
\ new[-session]
\ next-layout
\ nextl
\ next[-window]
\ paste-buffer
\ pasteb
\ pipe-pane
\ pipep
\ previous-layout
\ prevl
\ prev[ious-window]
\ refresh[-client]
\ rename[-session]
\ rename-window
\ renamew
\ resize-pane
\ resizep
\ respawn-pane
\ respawnp
\ respawn-window
\ respawnw
\ rotate-window
\ rotatew
\ run[-shell]
\ save-buffer
\ saveb
\ select-layout
\ selectl
\ select-pane
\ selectp
\ select-window
\ selectw
\ send[-keys]
\ send-prefix
\ server-info
\ info
\ set-buffer
\ setb
\ set-environment
\ setenv
\ set[-option]
\ set-window-option
\ setw
\ show-buffer
\ showb
\ show-environment
\ showenv
\ show-messages
\ showmsgs
\ show[-options]
\ show-window-options
\ showw
\ source[-file]
\ split-window
\ splitw
\ start[-server]
\ suspend-client
\ suspendc
\ swap-pane
\ swapp
\ swap-window
\ swapw
\ switch-client
\ switchc
\ unbind[-key]
\ unlink-window
\ unlinkw
\ wait[-for]
syn keyword tmuxOptsSet
\ assume-paste-time
\ base-index
\ bell-action
\ bell-on-alert
\ buffer-limit
\ default-command
\ default-shell
\ default-terminal
\ destroy-unattached
\ detach-on-destroy
\ display-panes-active-colour
\ display-panes-colour
\ display-panes-time
\ display-time
\ escape-time
\ exit-unattached
\ focus-events
\ history-file
\ history-limit
\ lock-after-time
\ lock-command
\ lock-server
\ message-command-style
\ message-limit
\ message-style
\ mouse
\ mouse-utf8
\ pane-active-border-style
\ pane-border-style
\ prefix
\ prefix2
\ quiet
\ renumber-windows
\ repeat-time
\ set-clipboard
\ set-remain-on-exit
\ set-titles
\ set-titles-string
\ status
\ status-interval
\ status-justify
\ status-keys
\ status-left
\ status-left-length
\ status-left-style
\ status-position
\ status-right
\ status-right-length
\ status-utf8
\ staus-right-style
\ terminal-overrides
\ update-environment
\ visual-activity
\ visual-bell
\ visual-silence
\ word-separators
syn keyword tmuxOptsSetw
\ aggressive-resize
\ allow-rename
\ alternate-screen
\ automatic-rename
\ clock-mode-colour
\ clock-mode-style
\ force-height
\ force-width
\ main-pane-height
\ main-pane-width
\ mode-keys
\ mode-style
\ monitor-activity
\ monitor-silence
\ other-pane-height
\ other-pane-width
\ pane-base-index
\ remain-on-exit
\ synchronize-panes
\ utf8
\ window-active-style
\ window-status-activity-style
\ window-status-bell-style
\ window-status-current-format
\ window-status-current-style
\ window-status-format
\ window-status-last-style
\ window-status-separator
\ window-status-style
\ window-style
\ wrap-search
\ xterm-keys
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
syn match tmuxKey /\(C-\|M-\|\^\)\+\S\+/ display
syn match tmuxNumber /\d\+/ display
syn match tmuxOptions /\s-\a\+/ display
syn match tmuxVariable /\w\+=/ display
syn match tmuxVariableExpansion /\${\=\w\+}\=/ display
" Comments can span multiple lines, when the newline is escaped
" (with a single) backslash at the end.
syn region tmuxComment start=/#/ skip=/\\\@<!\\$/ end=/$/ contains=tmuxTodo
syn region tmuxString start=/"/ end=/"/ display oneline
syn region tmuxString start=/'/ end=/'/ display oneline
hi def link tmuxAction Boolean
hi def link tmuxBoolean Boolean
hi def link tmuxCmds Keyword
hi def link tmuxComment Comment
hi def link tmuxKey Special
hi def link tmuxNumber Number
hi def link tmuxOptions Identifier
hi def link tmuxOptsSet Function
hi def link tmuxOptsSetw Function
hi def link tmuxString String
hi def link tmuxTodo Todo
hi def link tmuxVariable Constant
hi def link tmuxVariableExpansion Constant
let b:current_syntax = "tmux"

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