Compare commits

..

No commits in common. "master" and "3.2" have entirely different histories.
master ... 3.2

199 changed files with 6602 additions and 25990 deletions

View File

@ -29,7 +29,7 @@ uname -sp && tmux -V && echo $TERM
Also include:
- Your platform (Linux, macOS, or whatever).
- Your platform (Linux, OS X, or whatever).
- A brief description of the problem with steps to reproduce.
@ -37,8 +37,7 @@ Also include:
- Your terminal, and `$TERM` inside and outside of tmux.
- Logs from tmux (see below). Please attach logs to the issue directly rather
than using a download site or pastebin. Put in a zip file if necessary.
- Logs from tmux (see below).
- At most one or two screenshots, if helpful.
@ -77,8 +76,3 @@ The log files are:
- `tmux-out*.log`: output log file.
Please attach the log files to your issue.
## What does it mean if an issue is closed?
All it means is that work on the issue is not planned for the near future. See
the issue's comments to find out if contributions would be welcome.

View File

@ -1,12 +1,3 @@
---
name: Use this issue template
about: Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md
title: ''
labels: ''
assignees: ''
---
### Issue description
Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md

View File

@ -1 +0,0 @@
blank_issues_enabled: false

4
.github/README.md vendored
View File

@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created,
accessed, and controlled from a single screen. tmux may be detached from a
screen and continue running in the background, then later reattached.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
## Dependencies
@ -79,7 +79,7 @@ A small example configuration is in `example_tmux.conf`.
And a bash(1) completion file at:
https://github.com/scop/bash-completion/blob/main/completions/tmux
https://github.com/imomaliev/tmux-bash-completion
For debugging, run tmux with `-v` or `-vv` to generate server and client log
files in the current directory.

10
.github/lock.yml vendored Normal file
View File

@ -0,0 +1,10 @@
daysUntilLock: 30
skipCreatedBefore: false
exemptLabels: []
lockLabel: false
lockComment: >
This thread has been automatically locked since there has not been
any recent activity after it was closed. Please open a new issue for
related bugs.
setLockReason: false
#only: issues

View File

@ -1,34 +0,0 @@
name: 'Lock Threads'
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
discussions: write
concurrency:
group: lock-threads
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v5
with:
github-token: ${{ github.token }}
issue-inactive-days: '30'
issue-comment: >
This issue has been automatically locked since there
has not been any recent activity after it was closed.
pr-inactive-days: '60'
pr-comment: >
This pull request has been automatically locked since there
has not been any recent activity after it was closed.
discussion-inactive-days: '60'
discussion-comment: >
This discussion has been automatically locked since there
has not been any recent activity after it was closed.

27
.gitignore vendored
View File

@ -1,24 +1,23 @@
*.core
*.dSYM
*.diff
*.o
*.patch
*.swp
*~
*.diff
*.patch
*.core
core
tags
.deps/
.dirstamp
Makefile
Makefile.in
compat/.dirstamp
aclocal.m4
autom4te.cache/
cmd-parse.c
compat/.dirstamp
config.log
config.status
configure
core
etc/
fuzz/*-fuzzer
tags
tmux
Makefile
Makefile.in
configure
tmux.1.*
*.dSYM
cmd-parse.c
fuzz/*-fuzzer
.dirstamp

411
CHANGES
View File

@ -1,396 +1,3 @@
CHANGES FROM 3.4 TO 3.5
* Revamp extended keys support to more closely match xterm and support mode 2
as well as mode 1. This is a substantial change to key handling which changes
tmux to always request mode 2 from parent terminal, changes to an unambiguous
internal representation of keys, and adds an option (extended-keys-format) to
control the format similar to the xterm(1) formatOtherKeys resource.
* Clear an overlay (popup or menu) when command prompt is entered.
* Add copy-mode -d flag to scroll a page down if in copy mode already (matching
-e).
* Display hyperlinks in copy mode and add copy_cursor_hyperlink format to get
the hyperlink under the cursor.
* Add a prefix timeout option.
* Mouse move keys are not useful as key bindings because we do not turn them on
unless the application requests them. Ignore them so they do not cause the
prefix to be canceled
* Add search_count and search_count_partial formats in copy mode.
* Do not reset mouse pane if clicked on status line,
* Add mirrored versions of the main-horizontal and main-vertical layouts where
the main pane is bottom or right instead of top or left.
* Allow REP to work with Unicode characters.
* Fix size calculation of terminators for clipboard escape sequences.
* Treat CRLF as LF in config files where it is easy to do so.
* The Linux console has some bugs with bright colours, so add some workarounds
for it.
* If built with systemd, remove some environment variables it uses.
* Adjust the logic when deleting last buffer to better preserve the selection:
if selecting the element below the deleted one fails (because as the last
one), select the one above it instead.
* Add --enable-jemalloc to build with jemalloc memory allocator (since glibc
malloc is so poor).
* Add a way (refresh-client -r) for control mode clients to provide OSC 10 and
11 responses to tmux so they can set the default foreground and background
colours.
* Add N to search backwards in tree modes.
* Use default-shell for command prompt, #() and popups.
* Revert part of a change intended to improve search performance by skipping
parts of lines already searched, but which in fact skipped the ends of lines
altogether.
* Add a command-error hook when a command fails.
* Add an option allow-set-title to forbid applications from changing the pane
title.
* Correct handling of mouse up events (don't ignore all but the last released
button), and always process down event for double click.
* Fix a crash if focusing a pane that is exiting.
* Pick newest session (as documented) when looking for next session for
detach-on-destroy.
* Reduce default escape-time to 10 milliseconds.
* Add display-menu -M to always turn mouse on in a menu.
* Look for feature code 21 for DECSLRM and 28 for DECFRA in the device
attributes and also accept level 1.
* Fix crash if built with SIXEL and the SIXEL colour register is invalid; also
remove SIXEL images before reflow.
* Do not notify window-layout-changed if the window is about to be destroyed.
* Do not consider a selection present if it is empty for the selection_active
and selection_present format variables.
* Fix split-window -p.
CHANGES FROM 3.3a TO 3.4
* Add options keep-last and keep-group to destroy-unattached to keep the last
session whether in a group.
* Don't allow paste-buffer into dead panes.
* Add -t to source-file.
* Rewrite combined character handling to be more consistent and to support
newer Unicode combined characters.
* Add basic support for SIXEL if built with --enable-sixel.
* Add a session, pane and user mouse range types for the status line and add
format variables for mouse_status_line and mouse_status_range so they can be
associated with different commands in the key bindings.
* Add flag (-o) to next-prompt/previous-prompt to go to OSC 133 command output.
* Add options and flags for menu styles (menu-style, menu-border-style) similar
to those existing for popups.
* Add support for marking lines with a shell prompt based on the OSC 133 extension.
* Check for libterminfo for NetBSD.
* Add "us" to styles for underscore colour.
* Add flags (-c and -y) to change the confirm key and default behaviour of
confirm-before.
* Use ncurses' new tparm_s function (added in 6.4-20230424) instead of tparm so
it does not object to string arguments in c apabilities it doesn't already
know. Also ignore errors from tparm if using previous ncurses versions.
* Set default lock command to vlock on Linux if present at build time.
* Discard mouse sequences that have the right form but actually are invalid.
* Add support for spawning panes in separate cgroups with systemd and a
configure flag (--disable-cgroups) to turn off.
* Add a format (pane_unseen_changes) to show if there are unseen changes while
in a mode.
* Remove old buffer when renaming rather than complaining.
* Add an L modifier like P, W, S to loop over clients.
* Add -f to list-clients like the other list commands.
* Extend display-message to work for control clients.
* Add a flag to display-menu to select the manu item selected when the menu is
open.
* Have tmux recognise pasted text wrapped in bracket paste sequences, rather
than only forwarding them to the program inside.
* Have client return 1 if process is interrupted to an input pane.
* Query the client terminal for foreground and background colours and if OSC 10
or 11 is received but no colour has been set inside tmux, return the colour
from the first attached client.
* Add send-keys -K to handle keys directly as if typed (so look up in key
table).
* Process escape sequences in show-buffer.
* Add a -l flag to display-message to disable format expansion.
* Add paste-buffer-deleted notification and fix name of paste-buffer-changed.
* Do not attempt to connect to the socket as a client if systemd is active.
* Add scroll-top and scroll-bottom commands to scroll so cursor is at top or
bottom.
* Add a -T flag to capture-pane to stop at the last used cell instead of the
full width. Restore the previous behaviour by making it default to off unless
-J is used.
* Add message-line option to control where message and prompt go.
* Notification when a paste buffer is deleted.
* Add a Nobr terminfo(5) capability to tell tmux the terminal does not use bright
colours for bold.
* Change g and G to go to top and bottom in menus.
* Add a third state "all" to allow-passthrough to work even in invisible panes.
* Add support for OSC 8 hyperlinks.
* Store the time lines are scrolled into history and display in copy mode.
* Add a %config-error reply to control mode for configuration file errors since
reporting them in view mode is useless.
* A new feature flag (ignorefkeys) to ignore terminfo(5) function key
definitions for rxvt.
* Pass through first argument to OSC 52 (which clipboards to set) if the
application provides it.
* Expand arguments to send-keys, capture-pane, split-window, join-pane where it
makes sense to do so.
* Ignore named buffers when choosing a buffer if one is not specified by the user.
CHANGES FROM 3.3 TO 3.3a
* Do not crash when run-shell produces output from a config file.
* Do not unintentionally turn off all mouse mode when button mode is also
present.
CHANGES FROM 3.2a TO 3.3
* Add an ACL list for users connecting to the tmux socket. Users may be
forbidden from attaching, forced to attach read-only, or allowed to attach
read-write. A new command, server-access, configures the list. File system
permissions must still be configured manually.
* Emit window-layout-changed on swap-pane.
* Better error reporting when applying custom layouts.
* Handle ANSI escape sequences in run-shell output.
* Add pane_start_path to match start_command.
* Set PWD so shells have a hint about the real path.
* Do not allow pipe-pane on dead panes.
* Do not report mouse positions (incorrectly) above the maximum of 223 in
normal mouse mode.
* Add an option (default off) to control the passthrough escape sequence.
* Support more mouse buttons when the terminal sends them.
* Add a window-resized hook which is fired when the window is actually resized
which may be later than the client resize.
* Add next_session_id format with the next session ID.
* Add formats for client and server UID and user.
* Add argument to refresh-client -l to forward clipboard to a pane.
* Add remain-on-exit-format to set text shown when pane is dead.
* With split-window -f use percentages of window size not pane size.
* Add an option (fill-character) to set the character used for unused areas of
a client.
* Add an option (scroll-on-clear) to control if tmux scrolls into history on
clear.
* Add a capability for OSC 7 and use it similarly to how the title is set (and
controlled by the same set-titles option).
* Add support for systemd socket activation (where systemd creates the Unix
domain socket for tmux rather than tmux creating it). Build with
--enable-systemd.
* Add an option (pane-border-indicators) to select how the active pane is shown
on the pane border (colour, arrows or both).
* Support underscore styles with capture-pane -e.
* Make pane-border-format a pane option rather than window.
* Respond to OSC 4 queries
* Fix g/G keys in modes to do the same thing as copy mode (and vi).
* Bump the time terminals have to respond to device attributes queries to three
seconds.
* If automatic-rename is off, allow the rename escape sequence to set an empty
name.
* Trim menu item text more intelligently.
* Add cursor-style and cursor-colour options to set the default cursor style
and colour.
* Accept some useful and non-conflicting emacs keys in vi normal mode at the
command prompt.
* Add a format modifier (c) to force a colour to RGB.
* Add -s and -S to display-popup to set styles, -b to set lines and -T to set
popup title. New popup-border-lines, popup-border-style and popup-style
options set the defaults.
* Add -e flag to set an environment variable for a popup.
* Make send-keys without arguments send the key it is bound to (if bound to a
key).
* Try to leave terminal cursor at the right position even when tmux is drawing
its own cursor or selection (such as at the command prompt and in choose
mode) for people using screen readers and similar which can make use of it.
* Change so that {} is converted to tmux commands immediately when parsed. This
means it must contain valid tmux commands. For commands which expand %% and
%%%, this now only happens within string arguments. Use of nested aliases
inside {} is now forbidden. Processing of commands given in quotes remains
the same.
* Disable evports on SunOS since they are broken.
* Do not expand the file given with tmux -f so it can contain :s.
* Bump FORMAT_LOOP_LIMIT and add a log message when hit.
* Add a terminal feature for the mouse (since FreeBSD termcap does not have kmous).
* Forbid empty session names.
* Improve error reporting when the tmux /tmp directory cannot be created or
used.
* Give #() commands a one second grace period where the output is empty before
telling the user they aren't doing anything ("not ready").
* When building, pick default-terminal from the first of tmux-256color, tmux,
screen-256color, screen that is available on the build system (--with-TERM
can override).
* Do not close popups on resize, instead adjust them to fit.
* Add a client-active hook.
* Make window-linked and window-unlinked window options.
* Do not configure on macOS without the user making a choice about utf8proc
(either --enable-utf8proc or --disable-utf8proc).
* Do not freeze output in panes when a popup is open, let them continue to
redraw.
* Add pipe variants of the line copy commands.
* Change copy-line and copy-end-of-line not to cancel and add -and-cancel
variants, like the other copy commands.
* Support the OSC palette-setting sequences in popups.
* Add a pane-colours array option to specify the defaults palette.
* Add support for Unicode zero-width joiner.
* Make newline a style delimiter as well so they can cross multiple lines for
readability in configuration files.
* Change focus to be driven by events rather than scanning panes so the
ordering of in and out is consistent.
* Add display-popup -B to open a popup without a border.
* Add a menu for popups that can be opened with button three outside the popup
or on the left or top border. Resizing now only works on the right and bottom
borders or when using Meta. The menu allows a popup to be closed, expanded to
the full size of the client, centered in the client or changed into a pane.
* Make command-prompt and confirm-before block by default (like run-shell). A
new -b flags runs them in the background as before. Also set return code for
confirm-before.
* Change cursor style handling so tmux understands which sequences contain
blinking and sets the flag appropriately, means that it works whether cnorm
disables blinking or not. This now matches xterm's behaviour.
* More accurate vi(1) word navigation in copy mode and on the status line. This
changes the meaning of the word-separators option: setting it to the empty
string is equivalent to the previous behavior.
* Add -F for command-prompt and use it to fix "Rename" on the window menu.
* Add different command histories for different types of prompts ("command",
"search" etc).
CHANGES FROM 3.2 TO 3.2a
* Add an "always" value for the "extended-keys" option; if set then tmux will
forward extended keys to applications even if they do not request them.
* Add a "mouse" terminal feature so tmux can enable the mouse on terminals
where it is known to be supported even if terminfo(5) says otherwise.
* Do not expand the filename given to -f so it can contain colons.
* Fixes for problems with extended keys and modifiers, scroll region,
source-file, cross compiling, format modifiers and other minor issues.
CHANGES FROM 3.1c TO 3.2
* Add a flag to disable keys to close a message.
@ -422,7 +29,7 @@ CHANGES FROM 3.1c TO 3.2
* Add a -S flag to new-window to make it select the existing window if one
with the given name already exists rather than failing with an error.
* Add a format modifier to check if a window or session name exists (N/w or
* Addd a format modifier to check if a window or session name exists (N/w or
N/s).
* Add compat clock_gettime for older macOS.
@ -454,7 +61,7 @@ CHANGES FROM 3.1c TO 3.2
an option on all panes.
* Make replacement of ##s consistent when drawing formats, whether followed by
[ or not. Add a flag (e) to the q: format modifier to double up #s.
[ or not. Add a flag (e) to the q: format modifier to double up #s
* Add -N flag to display-panes to ignore keys.
@ -498,7 +105,7 @@ CHANGES FROM 3.1c TO 3.2
* Add a way for control mode clients to subscribe to a format and be notified
of changes rather than having to poll.
* Add some formats for search in copy mode (search_present, search_match).
* Do not wait on shutdown for commands started with run -b.
@ -622,7 +229,7 @@ CHANGES FROM 3.1c TO 3.2
only show windows and C-b . only targets.
* Change all the style options to string options so they can support formats.
Change pane-active-border-style to use this to change the border colour when
Change pane-border-active-style to use this to change the border colour when
in a mode or with synchronize-panes on. This also implies a few minor changes
to existing behaviour:
@ -658,7 +265,7 @@ CHANGES FROM 3.1c TO 3.2
* Wait until the initial command sequence is done before sending a device
attributes request and other bits that prompt a reply from the terminal. This
means that stray replies are not left on the terminal if the command has
means that stray relies are not left on the terminal if the command has
attached and then immediately detached and tmux will not be around to receive
them.
@ -673,7 +280,7 @@ CHANGES FROM 3.1c TO 3.2
window-renamed
window-unlinked
And these are now pane options:
And these now pane options:
pane-died
pane-exited
@ -748,7 +355,7 @@ CHANGES FROM 3.1c TO 3.2
* Add a default binding for button 2 to paste.
* Add -d flag to run-shell to delay before running the command and allow it to
be used without a command so it just delays.
run without a command so it just delays.
* Add C-g to cancel command prompt with vi keys as well as emacs, and q in
command mode.
@ -1504,7 +1111,7 @@ Incompatible Changes
bind -Tcopy-mode C-r command-prompt -i -p'search up' "send -X search-backward-incremental '%%'"
There are also some new commands available with send -X, such as
There are also some new commmands available with send -X, such as
copy-pipe-and-cancel.
* set-remain-on-exit has gone -- can be achieved with hooks instead.
* Hooks: before hooks have been removed and only a selection of commands now
@ -3480,7 +3087,7 @@ The list of older changes is below.
* (nicm) -n on new-session is now -s, and -n is now the initial window name.
This was documented but not implemented :-/.
* (nicm) kill-window command, bound to & by default (because it should be hard
to hit accidentally).
to hit accidently).
* (nicm) bell-style option with three choices: "none" completely ignore bell;
"any" pass through a bell in any window to current; "current" ignore bells
except in current window. This applies only to the bell terminal signal,

View File

@ -1,3 +1,5 @@
# Makefile.am
# Obvious program stuff.
bin_PROGRAMS = tmux
CLEANFILES = tmux.1.mdoc tmux.1.man cmd-parse.c
@ -11,9 +13,7 @@ dist_EXTRA_tmux_SOURCES = compat/*.[ch]
# Preprocessor flags.
AM_CPPFLAGS += @XOPEN_DEFINES@ \
-DTMUX_VERSION='"@VERSION@"' \
-DTMUX_CONF='"$(sysconfdir)/tmux.conf:~/.tmux.conf:$$XDG_CONFIG_HOME/tmux/tmux.conf:~/.config/tmux/tmux.conf"' \
-DTMUX_LOCK_CMD='"@DEFAULT_LOCK_CMD@"' \
-DTMUX_TERM='"@DEFAULT_TERM@"'
-DTMUX_CONF='"$(sysconfdir)/tmux.conf:~/.tmux.conf:$$XDG_CONFIG_HOME/tmux/tmux.conf:~/.config/tmux/tmux.conf"'
# Additional object files.
LDADD = $(LIBOBJS)
@ -29,9 +29,6 @@ AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
AM_CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
AM_CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
AM_CFLAGS += -Wno-unused-result -Wno-format-y2k
if IS_DARWIN
AM_CFLAGS += -Wno-deprecated-declarations -Wno-cast-align -Wno-macro-redefined
endif
AM_CPPFLAGS += -DDEBUG
endif
AM_CPPFLAGS += -iquote.
@ -66,11 +63,6 @@ if IS_HAIKU
AM_CPPFLAGS += -D_BSD_SOURCE
endif
# Set flags for Cygwin.
if IS_CYGWIN
AM_CPPFLAGS += -DTMUX_SOCK_PERM=0
endif
# List of sources.
dist_tmux_SOURCES = \
alerts.c \
@ -127,14 +119,12 @@ dist_tmux_SOURCES = \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
cmd-server-access.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-option.c \
cmd-show-environment.c \
cmd-show-messages.c \
cmd-show-options.c \
cmd-show-prompt-history.c \
cmd-source-file.c \
cmd-split-window.c \
cmd-swap-pane.c \
@ -154,7 +144,6 @@ dist_tmux_SOURCES = \
grid-reader.c \
grid-view.c \
grid.c \
hyperlinks.c \
input-keys.c \
input.c \
job.c \
@ -178,7 +167,6 @@ dist_tmux_SOURCES = \
screen-redraw.c \
screen-write.c \
screen.c \
server-acl.c \
server-client.c \
server-fn.c \
server.c \
@ -188,13 +176,11 @@ dist_tmux_SOURCES = \
style.c \
tmux.c \
tmux.h \
tmux-protocol.h \
tty-acs.c \
tty-features.c \
tty-keys.c \
tty-term.c \
tty.c \
utf8-combined.c \
utf8.c \
window-buffer.c \
window-client.c \
@ -212,21 +198,11 @@ if NEED_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
endif
# Add compat file for systemd.
if HAVE_SYSTEMD
nodist_tmux_SOURCES += compat/systemd.c
endif
# Add compat file for utf8proc.
if HAVE_UTF8PROC
nodist_tmux_SOURCES += compat/utf8proc.c
endif
# Enable sixel support.
if ENABLE_SIXEL
dist_tmux_SOURCES += image.c image-sixel.c
endif
if NEED_FUZZING
check_PROGRAMS = fuzz/input-fuzzer
fuzz_input_fuzzer_LDFLAGS = $(FUZZING_LIBS)

13
README
View File

@ -4,7 +4,7 @@ tmux is a terminal multiplexer: it enables a number of terminals to be created,
accessed, and controlled from a single screen. tmux may be detached from a
screen and continue running in the background, then later reattached.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, macOS and Solaris.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
* Dependencies
@ -36,7 +36,6 @@ autoconf, automake and pkg-config:
$ cd tmux
$ sh autogen.sh
$ ./configure && make
$ sudo make install
* Contributing
@ -56,17 +55,9 @@ source tree with:
A small example configuration is in example_tmux.conf.
Other documentation is available in the wiki:
https://github.com/tmux/tmux/wiki
Also see the tmux FAQ at:
https://github.com/tmux/tmux/wiki/FAQ
A bash(1) completion file is at:
https://github.com/scop/bash-completion/blob/main/completions/tmux
https://github.com/imomaliev/tmux-bash-completion
For debugging, run tmux with -v and -vv to generate server and client log files
in the current directory.

View File

@ -3,7 +3,7 @@ tmuxへようこそ!
tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。
バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。
OpenBSD、FreeBSD、NetBSD、Linux、macOS、Solarisで実行できます。
OpenBSD、FreeBSD、NetBSD、Linux、OS X、Solarisで実行できます。
tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。
@ -38,7 +38,7 @@ tmuxのドキュメントについてはtmux.1マニュアルをご覧くださ
サンプル設定は本リポジトリのexample_tmux.confに
また、bash-completionファイルは下記にあります。
https://github.com/scop/bash-completion/blob/main/completions/tmux
https://github.com/imomaliev/tmux-bash-completion
「-v」や「-vv」を指定することでデバッグモードでの起動が可能です。カレントディレクトリにサーバーやクライアントのログファイルが生成されます。

34
SYNCING
View File

@ -1,17 +1,17 @@
Preamble
========
Tmux portable relies on repositories "tmux" and "tmux-obsd".
Tmux portable relies on repositories "tmux" and "tmux-openbsd".
Here's a description of them:
* "tmux" is the portable version, the one which contains code for other
operating systems, and autotools, etc., which isn't found or needed in the
OpenBSD base system.
* "tmux-obsd" is the version of tmux in OpenBSD base system which provides
* "tmux-openbsd" is the version of tmux in OpenBSD base system which provides
the basis of the portable tmux version.
Note: The "tmux-obsd" repository is actually handled by "git cvsimport"
Note: The "tmux-openbsd" repository is actually handled by "git cvsimport"
running at 15 minute intervals, so a commit made to OpenBSD's tmux CVS
repository will take at least that long to appear in this git repository.
(It might take longer, depending on the CVS mirror used to import the
@ -34,11 +34,11 @@ this information has ever been set before.
Cloning repositories
====================
This involves having both tmux and tmux-obsd cloned, as in:
This involves having both tmux and tmux-openbsd cloned, as in:
% cd /some/where/useful
% git clone https://github.com/tmux/tmux.git
% git clone https://github.com/ThomasAdam/tmux-obsd.git
% git clone https://github.com/ThomasAdam/tmux-openbsd.git
Note that you do not need additional checkouts to manage the sync -- an
existing clone of either repositories will suffice. So if you already have
@ -47,30 +47,30 @@ these checkouts existing, skip that.
Adding in git-remotes
=====================
Because the portable "tmux" git repository and the "tmux-obsd"
Because the portable "tmux" git repository and the "tmux-openbsd"
repository do not inherently share any history between each other, the
history has been faked between them. This "faking of history" is something
which has to be told to git for the purposes of comparing the "tmux" and
"tmux-obsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-obsd" repository from the "tmux" repository, as
"tmux-openbsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-openbsd" repository from the "tmux" repository, as
shown by the following command:
% cd /path/to/tmux
% git remote add obsd-tmux file:///path/to/tmux-obsd
% git remote add obsd-tmux file:///path/to/tmux-openbsd
So that now, the remote "obsd-tmux" can be used to reference branches and
commits from the "tmux-obsd" repository, but from the context of the
commits from the "tmux-openbsd" repository, but from the context of the
portable "tmux" repository, which makes sense because it's the "tmux"
repository which will have the updates applied to them.
Fetching updates
================
To ensure the latest commits from "tmux-obsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-obsd" is
To ensure the latest commits from "tmux-openbsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-openbsd" is
up-to-date first, and then reference that update in "tmux", as in:
% cd /path/to/tmux-obsd
% cd /path/to/tmux-openbsd
% git checkout master
% git pull
@ -82,17 +82,17 @@ Then back in "tmux":
Creating the necessary branches
===============================
Now that "tmux" can see commits and branches from "tmux-obsd" by way
Now that "tmux" can see commits and branches from "tmux-openbsd" by way
of the remote name "obsd-tmux", we can now create the master branch from
"tmux-obsd" in the "tmux" repository:
"tmux-openbsd" in the "tmux" repository:
% git checkout -b obsd-master obsd-tmux/master
Adding in the fake history points
=================================
=================================
To tie both the "master" branch from "tmux" and the "obsd-master"
branch from "tmux-obsd" together, the fake history points added to the
branch from "tmux-openbsd" together, the fake history points added to the
"tmux" repository need to be added. To do this, we must add an
additional refspec line, as in:

View File

@ -315,11 +315,11 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option)
if (visual == VISUAL_OFF)
continue;
if (c->session->curw == wl) {
status_message_set(c, -1, 1, 0, 0,
"%s in current window", type);
status_message_set(c, -1, 1, 0, "%s in current window",
type);
} else {
status_message_set(c, -1, 1, 0, 0,
"%s in window %d", type, wl->idx);
status_message_set(c, -1, 1, 0, "%s in window %d", type,
wl->idx);
}
}
}

View File

@ -18,7 +18,6 @@
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -29,35 +28,19 @@
* Manipulate command arguments.
*/
/* List of argument values. */
struct args_value {
char *value;
TAILQ_ENTRY(args_value) entry;
};
TAILQ_HEAD(args_values, args_value);
/* Single arguments flag. */
struct args_entry {
u_char flag;
struct args_values values;
u_int count;
int flags;
#define ARGS_ENTRY_OPTIONAL_VALUE 0x1
RB_ENTRY(args_entry) entry;
};
/* Parsed argument flags and values. */
struct args {
struct args_tree tree;
u_int count;
struct args_value *values;
};
/* Prepared command state. */
struct args_command_state {
struct cmd_list *cmdlist;
char *cmd;
struct cmd_parse_input pi;
};
static struct args_entry *args_find(struct args *, u_char);
static int args_cmp(struct args_entry *, struct args_entry *);
@ -80,348 +63,38 @@ args_find(struct args *args, u_char flag)
return (RB_FIND(args_tree, &args->tree, &entry));
}
/* Copy value. */
static void
args_copy_value(struct args_value *to, struct args_value *from)
{
to->type = from->type;
switch (from->type) {
case ARGS_NONE:
break;
case ARGS_COMMANDS:
to->cmdlist = from->cmdlist;
to->cmdlist->references++;
break;
case ARGS_STRING:
to->string = xstrdup(from->string);
break;
}
}
/* Type to string. */
static const char *
args_type_to_string (enum args_type type)
{
switch (type)
{
case ARGS_NONE:
return "NONE";
case ARGS_STRING:
return "STRING";
case ARGS_COMMANDS:
return "COMMANDS";
}
return "INVALID";
}
/* Get value as string. */
static const char *
args_value_as_string(struct args_value *value)
{
switch (value->type) {
case ARGS_NONE:
return ("");
case ARGS_COMMANDS:
if (value->cached == NULL)
value->cached = cmd_list_print(value->cmdlist, 0);
return (value->cached);
case ARGS_STRING:
return (value->string);
}
fatalx("unexpected argument type");
}
/* Create an empty arguments set. */
/* Parse an argv and argc into a new argument set. */
struct args *
args_create(void)
args_parse(const char *template, int argc, char **argv)
{
struct args *args;
struct args *args;
int opt;
args = xcalloc(1, sizeof *args);
RB_INIT(&args->tree);
return (args);
}
/* Parse a single flag. */
static int
args_parse_flag_argument(struct args_value *values, u_int count, char **cause,
struct args *args, u_int *i, const char *string, int flag,
int optional_argument)
{
struct args_value *argument, *new;
const char *s;
optreset = 1;
optind = 1;
optarg = NULL;
new = xcalloc(1, sizeof *new);
if (*string != '\0') {
new->type = ARGS_STRING;
new->string = xstrdup(string);
goto out;
}
if (*i == count)
argument = NULL;
else {
argument = &values[*i];
if (argument->type != ARGS_STRING) {
xasprintf(cause, "-%c argument must be a string", flag);
args_free_value(new);
free(new);
return (-1);
}
}
if (argument == NULL) {
args_free_value(new);
free(new);
if (optional_argument) {
log_debug("%s: -%c (optional)", __func__, flag);
args_set(args, flag, NULL, ARGS_ENTRY_OPTIONAL_VALUE);
return (0); /* either - or end */
}
xasprintf(cause, "-%c expects an argument", flag);
return (-1);
}
args_copy_value(new, argument);
(*i)++;
out:
s = args_value_as_string(new);
log_debug("%s: -%c = %s", __func__, flag, s);
args_set(args, flag, new, 0);
return (0);
}
/* Parse flags argument. */
static int
args_parse_flags(const struct args_parse *parse, struct args_value *values,
u_int count, char **cause, struct args *args, u_int *i)
{
struct args_value *value;
u_char flag;
const char *found, *string;
int optional_argument;
value = &values[*i];
if (value->type != ARGS_STRING)
return (1);
string = value->string;
log_debug("%s: next %s", __func__, string);
if (*string++ != '-' || *string == '\0')
return (1);
(*i)++;
if (string[0] == '-' && string[1] == '\0')
return (1);
for (;;) {
flag = *string++;
if (flag == '\0')
return (0);
if (flag == '?')
return (-1);
if (!isalnum(flag)) {
xasprintf(cause, "invalid flag -%c", flag);
return (-1);
}
found = strchr(parse->template, flag);
if (found == NULL) {
xasprintf(cause, "unknown flag -%c", flag);
return (-1);
}
if (found[1] != ':') {
log_debug("%s: -%c", __func__, flag);
args_set(args, flag, NULL, 0);
while ((opt = getopt(argc, argv, template)) != -1) {
if (opt < 0)
continue;
}
optional_argument = (found[2] == ':');
return (args_parse_flag_argument(values, count, cause, args, i,
string, flag, optional_argument));
}
}
/* Parse arguments into a new argument set. */
struct args *
args_parse(const struct args_parse *parse, struct args_value *values,
u_int count, char **cause)
{
struct args *args;
u_int i;
enum args_parse_type type;
struct args_value *value, *new;
const char *s;
int stop;
if (count == 0)
return (args_create());
args = args_create();
for (i = 1; i < count; /* nothing */) {
stop = args_parse_flags(parse, values, count, cause, args, &i);
if (stop == -1) {
if (opt == '?' || strchr(template, opt) == NULL) {
args_free(args);
return (NULL);
}
if (stop == 1)
break;
args_set(args, opt, optarg);
optarg = NULL;
}
log_debug("%s: flags end at %u of %u", __func__, i, count);
if (i != count) {
for (/* nothing */; i < count; i++) {
value = &values[i];
argc -= optind;
argv += optind;
s = args_value_as_string(value);
log_debug("%s: %u = %s (type %s)", __func__, i, s,
args_type_to_string (value->type));
args->argc = argc;
args->argv = cmd_copy_argv(argc, argv);
if (parse->cb != NULL) {
type = parse->cb(args, args->count, cause);
if (type == ARGS_PARSE_INVALID) {
args_free(args);
return (NULL);
}
} else
type = ARGS_PARSE_STRING;
args->values = xrecallocarray(args->values,
args->count, args->count + 1, sizeof *args->values);
new = &args->values[args->count++];
switch (type) {
case ARGS_PARSE_INVALID:
fatalx("unexpected argument type");
case ARGS_PARSE_STRING:
if (value->type != ARGS_STRING) {
xasprintf(cause,
"argument %u must be \"string\"",
args->count);
args_free(args);
return (NULL);
}
args_copy_value(new, value);
break;
case ARGS_PARSE_COMMANDS_OR_STRING:
args_copy_value(new, value);
break;
case ARGS_PARSE_COMMANDS:
if (value->type != ARGS_COMMANDS) {
xasprintf(cause,
"argument %u must be { commands }",
args->count);
args_free(args);
return (NULL);
}
args_copy_value(new, value);
break;
}
}
}
if (parse->lower != -1 && args->count < (u_int)parse->lower) {
xasprintf(cause,
"too few arguments (need at least %u)",
parse->lower);
args_free(args);
return (NULL);
}
if (parse->upper != -1 && args->count > (u_int)parse->upper) {
xasprintf(cause,
"too many arguments (need at most %u)",
parse->upper);
args_free(args);
return (NULL);
}
return (args);
}
/* Copy and expand a value. */
static void
args_copy_copy_value(struct args_value *to, struct args_value *from, int argc,
char **argv)
{
char *s, *expanded;
int i;
to->type = from->type;
switch (from->type) {
case ARGS_NONE:
break;
case ARGS_STRING:
expanded = xstrdup(from->string);
for (i = 0; i < argc; i++) {
s = cmd_template_replace(expanded, argv[i], i + 1);
free(expanded);
expanded = s;
}
to->string = expanded;
break;
case ARGS_COMMANDS:
to->cmdlist = cmd_list_copy(from->cmdlist, argc, argv);
break;
}
}
/* Copy an arguments set. */
struct args *
args_copy(struct args *args, int argc, char **argv)
{
struct args *new_args;
struct args_entry *entry;
struct args_value *value, *new_value;
u_int i;
cmd_log_argv(argc, argv, "%s", __func__);
new_args = args_create();
RB_FOREACH(entry, args_tree, &args->tree) {
if (TAILQ_EMPTY(&entry->values)) {
for (i = 0; i < entry->count; i++)
args_set(new_args, entry->flag, NULL, 0);
continue;
}
TAILQ_FOREACH(value, &entry->values, entry) {
new_value = xcalloc(1, sizeof *new_value);
args_copy_copy_value(new_value, value, argc, argv);
args_set(new_args, entry->flag, new_value, 0);
}
}
if (args->count == 0)
return (new_args);
new_args->count = args->count;
new_args->values = xcalloc(args->count, sizeof *new_args->values);
for (i = 0; i < args->count; i++) {
new_value = &new_args->values[i];
args_copy_copy_value(new_value, &args->values[i], argc, argv);
}
return (new_args);
}
/* Free a value. */
void
args_free_value(struct args_value *value)
{
switch (value->type) {
case ARGS_NONE:
break;
case ARGS_STRING:
free(value->string);
break;
case ARGS_COMMANDS:
cmd_list_free(value->cmdlist);
break;
}
free(value->cached);
}
/* Free values. */
void
args_free_values(struct args_value *values, u_int count)
{
u_int i;
for (i = 0; i < count; i++)
args_free_value(&values[i]);
}
/* Free an arguments set. */
void
args_free(struct args *args)
@ -431,14 +104,13 @@ args_free(struct args *args)
struct args_value *value;
struct args_value *value1;
args_free_values(args->values, args->count);
free(args->values);
cmd_free_argv(args->argc, args->argv);
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
RB_REMOVE(args_tree, &args->tree, entry);
TAILQ_FOREACH_SAFE(value, &entry->values, entry, value1) {
TAILQ_REMOVE(&entry->values, value, entry);
args_free_value(value);
free(value->value);
free(value);
}
free(entry);
@ -447,52 +119,11 @@ args_free(struct args *args)
free(args);
}
/* Convert arguments to vector. */
void
args_to_vector(struct args *args, int *argc, char ***argv)
{
char *s;
u_int i;
*argc = 0;
*argv = NULL;
for (i = 0; i < args->count; i++) {
switch (args->values[i].type) {
case ARGS_NONE:
break;
case ARGS_STRING:
cmd_append_argv(argc, argv, args->values[i].string);
break;
case ARGS_COMMANDS:
s = cmd_list_print(args->values[i].cmdlist, 0);
cmd_append_argv(argc, argv, s);
free(s);
break;
}
}
}
/* Convert arguments from vector. */
struct args_value *
args_from_vector(int argc, char **argv)
{
struct args_value *values;
int i;
values = xcalloc(argc, sizeof *values);
for (i = 0; i < argc; i++) {
values[i].type = ARGS_STRING;
values[i].string = xstrdup(argv[i]);
}
return (values);
}
/* Add to string. */
static void printflike(3, 4)
args_print_add(char **buf, size_t *len, const char *fmt, ...)
{
va_list ap;
va_list ap;
char *s;
size_t slen;
@ -509,37 +140,44 @@ args_print_add(char **buf, size_t *len, const char *fmt, ...)
/* Add value to string. */
static void
args_print_add_value(char **buf, size_t *len, struct args_value *value)
args_print_add_value(char **buf, size_t *len, struct args_entry *entry,
struct args_value *value)
{
char *expanded = NULL;
char *escaped;
if (**buf != '\0')
args_print_add(buf, len, " -%c ", entry->flag);
else
args_print_add(buf, len, "-%c ", entry->flag);
escaped = args_escape(value->value);
args_print_add(buf, len, "%s", escaped);
free(escaped);
}
/* Add argument to string. */
static void
args_print_add_argument(char **buf, size_t *len, const char *argument)
{
char *escaped;
if (**buf != '\0')
args_print_add(buf, len, " ");
switch (value->type) {
case ARGS_NONE:
break;
case ARGS_COMMANDS:
expanded = cmd_list_print(value->cmdlist, 0);
args_print_add(buf, len, "{ %s }", expanded);
break;
case ARGS_STRING:
expanded = args_escape(value->string);
args_print_add(buf, len, "%s", expanded);
break;
}
free(expanded);
escaped = args_escape(argument);
args_print_add(buf, len, "%s", escaped);
free(escaped);
}
/* Print a set of arguments. */
char *
args_print(struct args *args)
{
size_t len;
size_t len;
char *buf;
u_int i, j;
int i;
u_int j;
struct args_entry *entry;
struct args_entry *last = NULL;
struct args_value *value;
len = 1;
@ -547,8 +185,6 @@ args_print(struct args *args)
/* Process the flags first. */
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE)
continue;
if (!TAILQ_EMPTY(&entry->values))
continue;
@ -560,31 +196,13 @@ args_print(struct args *args)
/* Then the flags with arguments. */
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->flags & ARGS_ENTRY_OPTIONAL_VALUE) {
if (*buf != '\0')
args_print_add(&buf, &len, " -%c", entry->flag);
else
args_print_add(&buf, &len, "-%c", entry->flag);
last = entry;
continue;
}
if (TAILQ_EMPTY(&entry->values))
continue;
TAILQ_FOREACH(value, &entry->values, entry) {
if (*buf != '\0')
args_print_add(&buf, &len, " -%c", entry->flag);
else
args_print_add(&buf, &len, "-%c", entry->flag);
args_print_add_value(&buf, &len, value);
}
last = entry;
TAILQ_FOREACH(value, &entry->values, entry)
args_print_add_value(&buf, &len, entry, value);
}
if (last && (last->flags & ARGS_ENTRY_OPTIONAL_VALUE))
args_print_add(&buf, &len, " --");
/* And finally the argument vector. */
for (i = 0; i < args->count; i++)
args_print_add_value(&buf, &len, &args->values[i]);
for (i = 0; i < args->argc; i++)
args_print_add_argument(&buf, &len, args->argv[i]);
return (buf);
}
@ -593,7 +211,7 @@ args_print(struct args *args)
char *
args_escape(const char *s)
{
static const char dquoted[] = " #';${}%";
static const char dquoted[] = " #';${}";
static const char squoted[] = " \"";
char *escaped, *result;
int flags, quotes = 0;
@ -650,24 +268,26 @@ args_has(struct args *args, u_char flag)
/* Set argument value in the arguments tree. */
void
args_set(struct args *args, u_char flag, struct args_value *value, int flags)
args_set(struct args *args, u_char flag, const char *s)
{
struct args_entry *entry;
struct args_value *value;
entry = args_find(args, flag);
if (entry == NULL) {
entry = xcalloc(1, sizeof *entry);
entry->flag = flag;
entry->count = 1;
entry->flags = flags;
TAILQ_INIT(&entry->values);
RB_INSERT(args_tree, &args->tree, entry);
} else
entry->count++;
if (value != NULL && value->type != ARGS_NONE)
if (s != NULL) {
value = xcalloc(1, sizeof *value);
value->value = xstrdup(s);
TAILQ_INSERT_TAIL(&entry->values, value, entry);
else
free(value);
}
}
/* Get argument value. Will be NULL if it isn't present. */
@ -680,7 +300,7 @@ args_get(struct args *args, u_char flag)
return (NULL);
if (TAILQ_EMPTY(&entry->values))
return (NULL);
return (TAILQ_LAST(&entry->values, args_values)->string);
return (TAILQ_LAST(&entry->values, args_values)->value);
}
/* Get first argument. */
@ -703,194 +323,31 @@ args_next(struct args_entry **entry)
return ((*entry)->flag);
}
/* Get argument count. */
u_int
args_count(struct args *args)
{
return (args->count);
}
/* Get argument values. */
struct args_value *
args_values(struct args *args)
{
return (args->values);
}
/* Get argument value. */
struct args_value *
args_value(struct args *args, u_int idx)
{
if (idx >= args->count)
return (NULL);
return (&args->values[idx]);
}
/* Return argument as string. */
const char *
args_string(struct args *args, u_int idx)
{
if (idx >= args->count)
return (NULL);
return (args_value_as_string(&args->values[idx]));
}
/* Make a command now. */
struct cmd_list *
args_make_commands_now(struct cmd *self, struct cmdq_item *item, u_int idx,
int expand)
{
struct args_command_state *state;
char *error;
struct cmd_list *cmdlist;
state = args_make_commands_prepare(self, item, idx, NULL, 0, expand);
cmdlist = args_make_commands(state, 0, NULL, &error);
if (cmdlist == NULL) {
cmdq_error(item, "%s", error);
free(error);
}
else
cmdlist->references++;
args_make_commands_free(state);
return (cmdlist);
}
/* Save bits to make a command later. */
struct args_command_state *
args_make_commands_prepare(struct cmd *self, struct cmdq_item *item, u_int idx,
const char *default_command, int wait, int expand)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
struct args_value *value;
struct args_command_state *state;
const char *cmd;
const char *file;
state = xcalloc(1, sizeof *state);
if (idx < args->count) {
value = &args->values[idx];
if (value->type == ARGS_COMMANDS) {
state->cmdlist = value->cmdlist;
state->cmdlist->references++;
return (state);
}
cmd = value->string;
} else {
if (default_command == NULL)
fatalx("argument out of range");
cmd = default_command;
}
if (expand)
state->cmd = format_single_from_target(item, cmd);
else
state->cmd = xstrdup(cmd);
log_debug("%s: %s", __func__, state->cmd);
if (wait)
state->pi.item = item;
cmd_get_source(self, &file, &state->pi.line);
if (file != NULL)
state->pi.file = xstrdup(file);
state->pi.c = tc;
if (state->pi.c != NULL)
state->pi.c->references++;
cmd_find_copy_state(&state->pi.fs, target);
return (state);
}
/* Return argument as command. */
struct cmd_list *
args_make_commands(struct args_command_state *state, int argc, char **argv,
char **error)
{
struct cmd_parse_result *pr;
char *cmd, *new_cmd;
int i;
if (state->cmdlist != NULL) {
if (argc == 0)
return (state->cmdlist);
return (cmd_list_copy(state->cmdlist, argc, argv));
}
cmd = xstrdup(state->cmd);
log_debug("%s: %s", __func__, cmd);
cmd_log_argv(argc, argv, __func__);
for (i = 0; i < argc; i++) {
new_cmd = cmd_template_replace(cmd, argv[i], i + 1);
log_debug("%s: %%%u %s: %s", __func__, i + 1, argv[i], new_cmd);
free(cmd);
cmd = new_cmd;
}
log_debug("%s: %s", __func__, cmd);
pr = cmd_parse_from_string(cmd, &state->pi);
free(cmd);
switch (pr->status) {
case CMD_PARSE_ERROR:
*error = pr->error;
return (NULL);
case CMD_PARSE_SUCCESS:
return (pr->cmdlist);
}
fatalx("invalid parse return state");
}
/* Free commands state. */
void
args_make_commands_free(struct args_command_state *state)
{
if (state->cmdlist != NULL)
cmd_list_free(state->cmdlist);
if (state->pi.c != NULL)
server_client_unref(state->pi.c);
free((void *)state->pi.file);
free(state->cmd);
free(state);
}
/* Get prepared command. */
char *
args_make_commands_get_command(struct args_command_state *state)
{
struct cmd *first;
int n;
char *s;
if (state->cmdlist != NULL) {
first = cmd_list_first(state->cmdlist);
if (first == NULL)
return (xstrdup(""));
return (xstrdup(cmd_get_entry(first)->name));
}
n = strcspn(state->cmd, " ,");
xasprintf(&s, "%.*s", n, state->cmd);
return (s);
}
/* Get first value in argument. */
struct args_value *
args_first_value(struct args *args, u_char flag)
const char *
args_first_value(struct args *args, u_char flag, struct args_value **value)
{
struct args_entry *entry;
if ((entry = args_find(args, flag)) == NULL)
return (NULL);
return (TAILQ_FIRST(&entry->values));
*value = TAILQ_FIRST(&entry->values);
if (*value == NULL)
return (NULL);
return ((*value)->value);
}
/* Get next value in argument. */
struct args_value *
args_next_value(struct args_value *value)
const char *
args_next_value(struct args_value **value)
{
return (TAILQ_NEXT(value, entry));
if (*value == NULL)
return (NULL);
*value = TAILQ_NEXT(*value, entry);
if (*value == NULL)
return (NULL);
return ((*value)->value);
}
/* Convert an argument value to a number. */
@ -899,7 +356,7 @@ args_strtonum(struct args *args, u_char flag, long long minval,
long long maxval, char **cause)
{
const char *errstr;
long long ll;
long long ll;
struct args_entry *entry;
struct args_value *value;
@ -908,49 +365,8 @@ args_strtonum(struct args *args, u_char flag, long long minval,
return (0);
}
value = TAILQ_LAST(&entry->values, args_values);
if (value == NULL ||
value->type != ARGS_STRING ||
value->string == NULL) {
*cause = xstrdup("missing");
return (0);
}
ll = strtonum(value->string, minval, maxval, &errstr);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);
}
*cause = NULL;
return (ll);
}
/* Convert an argument value to a number, and expand formats. */
long long
args_strtonum_and_expand(struct args *args, u_char flag, long long minval,
long long maxval, struct cmdq_item *item, char **cause)
{
const char *errstr;
char *formatted;
long long ll;
struct args_entry *entry;
struct args_value *value;
if ((entry = args_find(args, flag)) == NULL) {
*cause = xstrdup("missing");
return (0);
}
value = TAILQ_LAST(&entry->values, args_values);
if (value == NULL ||
value->type != ARGS_STRING ||
value->string == NULL) {
*cause = xstrdup("missing");
return (0);
}
formatted = format_single_from_target(item, value->string);
ll = strtonum(formatted, minval, maxval, &errstr);
free(formatted);
ll = strtonum(value->value, minval, maxval, &errstr);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);
@ -972,11 +388,7 @@ args_percentage(struct args *args, u_char flag, long long minval,
*cause = xstrdup("missing");
return (0);
}
if (TAILQ_EMPTY(&entry->values)) {
*cause = xstrdup("empty");
return (0);
}
value = TAILQ_LAST(&entry->values, args_values)->string;
value = TAILQ_LAST(&entry->values, args_values)->value;
return (args_string_percentage(value, minval, maxval, curval, cause));
}
@ -986,14 +398,10 @@ args_string_percentage(const char *value, long long minval, long long maxval,
long long curval, char **cause)
{
const char *errstr;
long long ll;
long long ll;
size_t valuelen = strlen(value);
char *copy;
if (valuelen == 0) {
*cause = xstrdup("empty");
return (0);
}
if (value[valuelen - 1] == '%') {
copy = xstrdup(value);
copy[valuelen - 1] = '\0';
@ -1024,74 +432,3 @@ args_string_percentage(const char *value, long long minval, long long maxval,
*cause = NULL;
return (ll);
}
/*
* Convert an argument to a number which may be a percentage, and expand
* formats.
*/
long long
args_percentage_and_expand(struct args *args, u_char flag, long long minval,
long long maxval, long long curval, struct cmdq_item *item, char **cause)
{
const char *value;
struct args_entry *entry;
if ((entry = args_find(args, flag)) == NULL) {
*cause = xstrdup("missing");
return (0);
}
if (TAILQ_EMPTY(&entry->values)) {
*cause = xstrdup("empty");
return (0);
}
value = TAILQ_LAST(&entry->values, args_values)->string;
return (args_string_percentage_and_expand(value, minval, maxval, curval,
item, cause));
}
/*
* Convert a string to a number which may be a percentage, and expand formats.
*/
long long
args_string_percentage_and_expand(const char *value, long long minval,
long long maxval, long long curval, struct cmdq_item *item, char **cause)
{
const char *errstr;
long long ll;
size_t valuelen = strlen(value);
char *copy, *f;
if (value[valuelen - 1] == '%') {
copy = xstrdup(value);
copy[valuelen - 1] = '\0';
f = format_single_from_target(item, copy);
ll = strtonum(f, 0, 100, &errstr);
free(f);
free(copy);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);
}
ll = (curval * ll) / 100;
if (ll < minval) {
*cause = xstrdup("too small");
return (0);
}
if (ll > maxval) {
*cause = xstrdup("too large");
return (0);
}
} else {
f = format_single_from_target(item, value);
ll = strtonum(f, minval, maxval, &errstr);
free(f);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);
}
}
*cause = NULL;
return (ll);
}

53
cfg.c
View File

@ -51,7 +51,8 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data)
return (CMD_RETURN_NORMAL);
cfg_finished = 1;
cfg_show_causes(NULL);
if (!RB_EMPTY(&sessions))
cfg_show_causes(RB_MIN(sessions, &sessions));
if (cfg_item != NULL)
cmdq_continue(cfg_item);
@ -66,7 +67,6 @@ start_cfg(void)
{
struct client *c;
u_int i;
int flags = 0;
/*
* Configuration files are loaded without a client, so commands are run
@ -84,17 +84,19 @@ start_cfg(void)
cmdq_append(c, cfg_item);
}
if (cfg_quiet)
flags = CMD_PARSE_QUIET;
for (i = 0; i < cfg_nfiles; i++)
load_cfg(cfg_files[i], c, NULL, NULL, flags, NULL);
for (i = 0; i < cfg_nfiles; i++) {
if (cfg_quiet)
load_cfg(cfg_files[i], c, NULL, CMD_PARSE_QUIET, NULL);
else
load_cfg(cfg_files[i], c, NULL, 0, NULL);
}
cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
}
int
load_cfg(const char *path, struct client *c, struct cmdq_item *item,
struct cmd_find_state *current, int flags, struct cmdq_item **new_item)
load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags,
struct cmdq_item **new_item)
{
FILE *f;
struct cmd_parse_input pi;
@ -122,6 +124,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item,
pr = cmd_parse_from_file(f, &pi);
fclose(f);
if (pr->status == CMD_PARSE_EMPTY)
return (0);
if (pr->status == CMD_PARSE_ERROR) {
cfg_add_cause("%s", pr->error);
free(pr->error);
@ -133,7 +137,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item,
}
if (item != NULL)
state = cmdq_copy_state(cmdq_get_state(item), current);
state = cmdq_copy_state(cmdq_get_state(item));
else
state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file);
@ -153,8 +157,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item,
int
load_cfg_from_buffer(const void *buf, size_t len, const char *path,
struct client *c, struct cmdq_item *item, struct cmd_find_state *current,
int flags, struct cmdq_item **new_item)
struct client *c, struct cmdq_item *item, int flags,
struct cmdq_item **new_item)
{
struct cmd_parse_input pi;
struct cmd_parse_result *pr;
@ -174,6 +178,8 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
pi.c = c;
pr = cmd_parse_from_buffer(buf, len, &pi);
if (pr->status == CMD_PARSE_EMPTY)
return (0);
if (pr->status == CMD_PARSE_ERROR) {
cfg_add_cause("%s", pr->error);
free(pr->error);
@ -185,7 +191,7 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path,
}
if (item != NULL)
state = cmdq_copy_state(cmdq_get_state(item), current);
state = cmdq_copy_state(cmdq_get_state(item));
else
state = cmdq_new_state(NULL, NULL, 0);
cmdq_add_format(state, "current_file", "%s", pi.file);
@ -236,29 +242,11 @@ cfg_print_causes(struct cmdq_item *item)
void
cfg_show_causes(struct session *s)
{
struct client *c = TAILQ_FIRST(&clients);
struct window_pane *wp;
struct window_mode_entry *wme;
u_int i;
if (cfg_ncauses == 0)
return;
if (c != NULL && (c->flags & CLIENT_CONTROL)) {
for (i = 0; i < cfg_ncauses; i++) {
control_write(c, "%%config-error %s", cfg_causes[i]);
free(cfg_causes[i]);
}
goto out;
}
if (s == NULL) {
if (c != NULL && c->session != NULL)
s = c->session;
else
s = RB_MIN(sessions, &sessions);
}
if (s == NULL || s->attached == 0) /* wait for an attached session */
if (s == NULL || cfg_ncauses == 0)
return;
wp = s->curw->window->active;
@ -266,11 +254,10 @@ cfg_show_causes(struct session *s)
if (wme == NULL || wme->mode != &window_view_mode)
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
for (i = 0; i < cfg_ncauses; i++) {
window_copy_add(wp, 0, "%s", cfg_causes[i]);
window_copy_add(wp, "%s", cfg_causes[i]);
free(cfg_causes[i]);
}
out:
free(cfg_causes);
cfg_causes = NULL;
cfg_ncauses = 0;

View File

@ -243,7 +243,9 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
ssize_t linelen;
char *line = NULL, **caps = NULL, *cause;
u_int ncaps = 0;
struct args_value *values;
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
signal(SIGCHLD, SIG_IGN);
/* Set up the initial command. */
if (shell_command != NULL) {
@ -256,20 +258,17 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
msg = MSG_COMMAND;
/*
* It's annoying parsing the command string twice (in client
* and later in server) but it is necessary to get the start
* server flag.
* It sucks parsing the command string twice (in client and
* later in server) but it is necessary to get the start server
* flag.
*/
values = args_from_vector(argc, argv);
pr = cmd_parse_from_arguments(values, argc, NULL);
pr = cmd_parse_from_arguments(argc, argv, NULL);
if (pr->status == CMD_PARSE_SUCCESS) {
if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER))
flags |= CLIENT_STARTSERVER;
cmd_list_free(pr->cmdlist);
} else
free(pr->error);
args_free_values(values, argc);
free(values);
}
/* Create client process structure (starts logging). */
@ -281,12 +280,6 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
log_debug("flags are %#llx", (unsigned long long)client_flags);
/* Initialize the client socket and start the server. */
#ifdef HAVE_SYSTEMD
if (systemd_activated()) {
/* socket-based activation, do not even try to be a client. */
fd = server_start(client_proc, flags, base, 0, NULL);
} else
#endif
fd = client_connect(base, socket_path, client_flags);
if (fd == -1) {
if (errno == ECONNREFUSED) {
@ -364,7 +357,6 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
/* Send identify messages. */
client_send_identify(ttynam, termname, caps, ncaps, cwd, feat);
tty_term_free_list(caps, ncaps);
proc_flush_peer(client_peer);
/* Send first command. */
if (msg == MSG_COMMAND) {
@ -452,12 +444,11 @@ client_send_identify(const char *ttynam, const char *termname, char **caps,
{
char **ss;
size_t sslen;
int fd;
uint64_t flags = client_flags;
int fd, flags = client_flags;
pid_t pid;
u_int i;
proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &flags, sizeof flags);
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &client_flags,
sizeof client_flags);
@ -498,10 +489,20 @@ client_send_identify(const char *ttynam, const char *termname, char **caps,
static __dead void
client_exec(const char *shell, const char *shellcmd)
{
char *argv0;
const char *name, *ptr;
char *argv0;
log_debug("shell %s, command %s", shell, shellcmd);
argv0 = shell_argv0(shell, !!(client_flags & CLIENT_LOGIN));
ptr = strrchr(shell, '/');
if (ptr != NULL && *(ptr + 1) != '\0')
name = ptr + 1;
else
name = shell;
if (client_flags & CLIENT_LOGIN)
xasprintf(&argv0, "-%s", name);
else
xasprintf(&argv0, "%s", name);
setenv("SHELL", shell, 1);
proc_clear_signals(client_proc, 1);
@ -521,23 +522,12 @@ client_signal(int sig)
{
struct sigaction sigact;
int status;
pid_t pid;
log_debug("%s: %s", __func__, strsignal(sig));
if (sig == SIGCHLD) {
for (;;) {
pid = waitpid(WAIT_ANY, &status, WNOHANG);
if (pid == 0)
break;
if (pid == -1) {
if (errno == ECHILD)
break;
log_debug("waitpid failed: %s",
strerror(errno));
}
}
} else if (!client_attached) {
if (sig == SIGTERM || sig == SIGHUP)
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
if (sig == SIGTERM)
proc_exit(client_proc);
} else {
switch (sig) {
@ -699,9 +689,6 @@ client_dispatch_wait(struct imsg *imsg)
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
NULL);
break;
case MSG_READ_CANCEL:
file_read_cancel(&client_files, imsg);
break;
case MSG_WRITE_OPEN:
file_write_open(&client_files, client_peer, imsg, 1,
!(client_flags & CLIENT_CONTROL), client_file_check_cb,

View File

@ -37,13 +37,13 @@ const struct cmd_entry cmd_attach_session_entry = {
.name = "attach-session",
.alias = "attach",
.args = { "c:dEf:rt:x", 0, 0, NULL },
.args = { "c:dEf:rt:x", 0, 0 },
.usage = "[-dErx] [-c working-directory] [-f flags] "
CMD_TARGET_SESSION_USAGE,
/* -t is special */
.flags = CMD_STARTSERVER|CMD_READONLY,
.flags = CMD_STARTSERVER,
.exec = cmd_attach_session_exec
};
@ -69,7 +69,6 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (c == NULL)
return (CMD_RETURN_NORMAL);
if (server_client_check_nested(c)) {
cmdq_error(item, "sessions should be nested with care, "
"unset $TMUX to force");
@ -125,9 +124,17 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (!Eflag)
environ_update(s->options, c->environ, s->environ);
server_client_set_session(c, s);
c->session = s;
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = c;
} else {
if (server_client_open(c, &cause) != 0) {
cmdq_error(item, "open terminal failed: %s", cause);
@ -149,17 +156,25 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (!Eflag)
environ_update(s->options, c->environ, s->environ);
server_client_set_session(c, s);
c->session = s;
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = c;
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
notify_client("client-attached", c);
c->flags |= CLIENT_ATTACHED;
}
if (cfg_finished)
cfg_show_causes(s);
recalculate_sizes();
alerts_check_session(s);
server_update_socket();
return (CMD_RETURN_NORMAL);
}

View File

@ -27,30 +27,20 @@
* Bind a key to a command.
*/
static enum args_parse_type cmd_bind_key_args_parse(struct args *, u_int,
char **);
static enum cmd_retval cmd_bind_key_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_bind_key_entry = {
.name = "bind-key",
.alias = "bind",
.args = { "nrN:T:", 1, -1, cmd_bind_key_args_parse },
.args = { "nrN:T:", 1, -1 },
.usage = "[-nr] [-T key-table] [-N note] key "
"[command [argument ...]]",
"[command [arguments]]",
.flags = CMD_AFTERHOOK,
.exec = cmd_bind_key_exec
};
static enum args_parse_type
cmd_bind_key_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
{
@ -58,13 +48,12 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
key_code key;
const char *tablename, *note = args_get(args, 'N');
struct cmd_parse_result *pr;
int repeat;
struct args_value *value;
u_int count = args_count(args);
char **argv = args->argv;
int argc = args->argc, repeat;
key = key_string_lookup_string(args_string(args, 0));
key = key_string_lookup_string(argv[0]);
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(item, "unknown key: %s", args_string(args, 0));
cmdq_error(item, "unknown key: %s", argv[0]);
return (CMD_RETURN_ERROR);
}
@ -76,32 +65,24 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
tablename = "prefix";
repeat = args_has(args, 'r');
if (count == 1) {
if (argc != 1) {
if (argc == 2)
pr = cmd_parse_from_string(argv[1], NULL);
else
pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL);
switch (pr->status) {
case CMD_PARSE_EMPTY:
cmdq_error(item, "empty command");
return (CMD_RETURN_ERROR);
case CMD_PARSE_ERROR:
cmdq_error(item, "%s", pr->error);
free(pr->error);
return (CMD_RETURN_ERROR);
case CMD_PARSE_SUCCESS:
break;
}
key_bindings_add(tablename, key, note, repeat, pr->cmdlist);
} else
key_bindings_add(tablename, key, note, repeat, NULL);
return (CMD_RETURN_NORMAL);
}
value = args_value(args, 1);
if (count == 2 && value->type == ARGS_COMMANDS) {
key_bindings_add(tablename, key, note, repeat, value->cmdlist);
value->cmdlist->references++;
return (CMD_RETURN_NORMAL);
}
if (count == 2)
pr = cmd_parse_from_string(args_string(args, 1), NULL);
else {
pr = cmd_parse_from_arguments(args_values(args) + 1, count - 1,
NULL);
}
switch (pr->status) {
case CMD_PARSE_ERROR:
cmdq_error(item, "%s", pr->error);
free(pr->error);
return (CMD_RETURN_ERROR);
case CMD_PARSE_SUCCESS:
break;
}
key_bindings_add(tablename, key, note, repeat, pr->cmdlist);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,7 +34,7 @@ const struct cmd_entry cmd_break_pane_entry = {
.name = "break-pane",
.alias = "breakp",
.args = { "abdPF:n:s:t:", 0, 0, NULL },
.args = { "abdPF:n:s:t:", 0, 0 },
.usage = "[-abdP] [-F format] [-n window-name] [-s src-pane] "
"[-t dst-window]",
@ -99,7 +99,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
options_set_parent(wp->options, w->options);
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
wp->flags |= PANE_STYLECHANGED;
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
w->latest = tc;
@ -115,7 +115,6 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
layout_init(w, wp);
wp->flags |= PANE_CHANGED;
colour_palette_from_option(&wp->palette, wp->options);
if (idx == -1)
idx = -1 - options_get_number(dst_s->options, "base-index");

View File

@ -39,8 +39,8 @@ const struct cmd_entry cmd_capture_pane_entry = {
.name = "capture-pane",
.alias = "capturep",
.args = { "ab:CeE:JMNpPqS:Tt:", 0, 0, NULL },
.usage = "[-aCeJMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
.args = { "ab:CeE:JNpPqS:t:", 0, 0 },
.usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] "
"[-S start-line] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -53,8 +53,8 @@ const struct cmd_entry cmd_clear_history_entry = {
.name = "clear-history",
.alias = "clearhist",
.args = { "Ht:", 0, 0, NULL },
.usage = "[-H] " CMD_TARGET_PANE_USAGE,
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -107,16 +107,14 @@ static char *
cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
struct window_pane *wp, size_t *len)
{
struct grid *gd;
const struct grid_line *gl;
struct screen *s;
struct grid_cell *gc = NULL;
struct window_mode_entry *wme;
int n, join_lines, flags = 0;
u_int i, sx, top, bottom, tmp;
char *cause, *buf, *line;
const char *Sflag, *Eflag;
size_t linelen;
struct grid *gd;
const struct grid_line *gl;
struct grid_cell *gc = NULL;
int n, with_codes, escape_c0, join_lines, no_trim;
u_int i, sx, top, bottom, tmp;
char *cause, *buf, *line;
const char *Sflag, *Eflag;
size_t linelen;
sx = screen_size_x(&wp->base);
if (args_has(args, 'a')) {
@ -128,27 +126,14 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
}
return (xstrdup(""));
}
s = &wp->base;
} else if (args_has(args, 'M')) {
wme = TAILQ_FIRST(&wp->modes);
if (wme != NULL && wme->mode->get_screen != NULL) {
s = wme->mode->get_screen (wme);
gd = s->grid;
} else {
s = &wp->base;
gd = wp->base.grid;
}
} else {
s = &wp->base;
} else
gd = wp->base.grid;
}
Sflag = args_get(args, 'S');
if (Sflag != NULL && strcmp(Sflag, "-") == 0)
top = 0;
else {
n = args_strtonum_and_expand(args, 'S', INT_MIN, SHRT_MAX,
item, &cause);
n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
top = gd->hsize;
free(cause);
@ -164,8 +149,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
if (Eflag != NULL && strcmp(Eflag, "-") == 0)
bottom = gd->hsize + gd->sy - 1;
else {
n = args_strtonum_and_expand(args, 'E', INT_MIN, SHRT_MAX,
item, &cause);
n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
free(cause);
@ -183,19 +167,15 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
top = tmp;
}
with_codes = args_has(args, 'e');
escape_c0 = args_has(args, 'C');
join_lines = args_has(args, 'J');
if (args_has(args, 'e'))
flags |= GRID_STRING_WITH_SEQUENCES;
if (args_has(args, 'C'))
flags |= GRID_STRING_ESCAPE_SEQUENCES;
if (!join_lines && !args_has(args, 'T'))
flags |= GRID_STRING_EMPTY_CELLS;
if (!join_lines && !args_has(args, 'N'))
flags |= GRID_STRING_TRIM_SPACES;
no_trim = args_has(args, 'N');
buf = NULL;
for (i = top; i <= bottom; i++) {
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
escape_c0, !join_lines && !no_trim);
linelen = strlen(line);
buf = cmd_capture_pane_append(buf, len, line, linelen);
@ -222,8 +202,6 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
if (cmd_get_entry(self) == &cmd_clear_history_entry) {
window_pane_reset_mode_all(wp);
grid_clear_history(wp->base.grid);
if (args_has(args, 'H'))
screen_reset_hyperlinks(wp->screen);
return (CMD_RETURN_NORMAL);
}

View File

@ -24,16 +24,13 @@
* Enter a mode.
*/
static enum args_parse_type cmd_choose_tree_args_parse(struct args *args,
u_int idx, char **cause);
static enum cmd_retval cmd_choose_tree_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_choose_tree_entry = {
.name = "choose-tree",
.alias = NULL,
.args = { "F:f:GK:NO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
.args = { "F:f:GK:NO:rst:wZ", 0, 1 },
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
@ -47,7 +44,7 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client",
.alias = NULL,
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.args = { "F:f:K:NO:rt:Z", 0, 1 },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
@ -61,7 +58,7 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.name = "choose-buffer",
.alias = NULL,
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
.args = { "F:f:K:NO:rt:Z", 0, 1 },
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
@ -75,7 +72,7 @@ const struct cmd_entry cmd_customize_mode_entry = {
.name = "customize-mode",
.alias = NULL,
.args = { "F:f:Nt:yZ", 0, 0, NULL },
.args = { "F:f:Nt:Z", 0, 0 },
.usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -84,13 +81,6 @@ const struct cmd_entry cmd_customize_mode_entry = {
.exec = cmd_choose_tree_exec
};
static enum args_parse_type
cmd_choose_tree_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
{
@ -100,7 +90,7 @@ cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
const struct window_mode *mode;
if (cmd_get_entry(self) == &cmd_choose_buffer_entry) {
if (paste_is_empty())
if (paste_get_top(NULL) == NULL)
return (CMD_RETURN_NORMAL);
mode = &window_buffer_mode;
} else if (cmd_get_entry(self) == &cmd_choose_client_entry) {

View File

@ -29,10 +29,8 @@
* Prompt for command in client.
*/
static enum args_parse_type cmd_command_prompt_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_command_prompt_exec(struct cmd *,
struct cmdq_item *);
static int cmd_command_prompt_callback(struct client *, void *,
const char *, int);
@ -42,112 +40,79 @@ const struct cmd_entry cmd_command_prompt_entry = {
.name = "command-prompt",
.alias = NULL,
.args = { "1bFkiI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
.usage = "[-1bFkiN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
" [-T prompt-type] [template]",
.args = { "1kiI:Np:Tt:W", 0, 1 },
.usage = "[-1kiNTW] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
"[template]",
.flags = CMD_CLIENT_TFLAG,
.exec = cmd_command_prompt_exec
};
struct cmd_command_prompt_prompt {
char *input;
char *prompt;
};
struct cmd_command_prompt_cdata {
struct cmdq_item *item;
struct args_command_state *state;
int flags;
int flags;
enum prompt_type prompt_type;
char *inputs;
char *next_input;
struct cmd_command_prompt_prompt *prompts;
u_int count;
u_int current;
char *prompts;
char *next_prompt;
int argc;
char **argv;
char *template;
int idx;
};
static enum args_parse_type
cmd_command_prompt_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct cmd_find_state *target = cmdq_get_target(item);
const char *type, *s, *input;
const char *inputs, *prompts;
struct cmd_command_prompt_cdata *cdata;
char *tmp, *prompts, *prompt, *next_prompt;
char *inputs = NULL, *next_input;
u_int count = args_count(args);
int wait = !args_has(args, 'b'), space = 1;
char *prompt, *ptr, *input = NULL;
size_t n;
if (tc->prompt_string != NULL)
return (CMD_RETURN_NORMAL);
if (args_has(args, 'i'))
wait = 0;
cdata = xcalloc(1, sizeof *cdata);
if (wait)
cdata->item = item;
cdata->state = args_make_commands_prepare(self, item, 0, "%1", wait,
args_has(args, 'F'));
if ((s = args_get(args, 'p')) == NULL) {
if (count != 0) {
tmp = args_make_commands_get_command(cdata->state);
xasprintf(&prompts, "(%s)", tmp);
free(tmp);
} else {
prompts = xstrdup(":");
space = 0;
}
next_prompt = prompts;
} else
next_prompt = prompts = xstrdup(s);
if ((s = args_get(args, 'I')) != NULL)
next_input = inputs = xstrdup(s);
cdata->inputs = NULL;
cdata->next_input = NULL;
cdata->prompts = NULL;
cdata->next_prompt = NULL;
cdata->template = NULL;
cdata->idx = 1;
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
next_input = NULL;
while ((prompt = strsep(&next_prompt, ",")) != NULL) {
cdata->prompts = xreallocarray(cdata->prompts, cdata->count + 1,
sizeof *cdata->prompts);
if (!space)
tmp = xstrdup(prompt);
else
xasprintf(&tmp, "%s ", prompt);
cdata->prompts[cdata->count].prompt = tmp;
cdata->template = xstrdup("%1");
if (next_input != NULL) {
input = strsep(&next_input, ",");
if (input == NULL)
input = "";
} else
input = "";
cdata->prompts[cdata->count].input = xstrdup(input);
cdata->count++;
}
free(inputs);
free(prompts);
if ((type = args_get(args, 'T')) != NULL) {
cdata->prompt_type = status_prompt_type(type);
if (cdata->prompt_type == PROMPT_TYPE_INVALID) {
cmdq_error(item, "unknown type: %s", type);
cmd_command_prompt_free(cdata);
return (CMD_RETURN_ERROR);
}
if ((prompts = args_get(args, 'p')) != NULL)
cdata->prompts = xstrdup(prompts);
else if (args->argc != 0) {
n = strcspn(cdata->template, " ,");
xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template);
} else
cdata->prompt_type = PROMPT_TYPE_COMMAND;
cdata->prompts = xstrdup(":");
/* Get first prompt. */
cdata->next_prompt = cdata->prompts;
ptr = strsep(&cdata->next_prompt, ",");
if (prompts == NULL)
prompt = xstrdup(ptr);
else
xasprintf(&prompt, "%s ", ptr);
/* Get initial prompt input. */
if ((inputs = args_get(args, 'I')) != NULL) {
cdata->inputs = xstrdup(inputs);
cdata->next_input = cdata->inputs;
input = strsep(&cdata->next_input, ",");
}
if (args_has(args, '1'))
cdata->flags |= PROMPT_SINGLE;
@ -157,71 +122,62 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
cdata->flags |= PROMPT_INCREMENTAL;
else if (args_has(args, 'k'))
cdata->flags |= PROMPT_KEY;
status_prompt_set(tc, target, cdata->prompts[0].prompt,
cdata->prompts[0].input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);
else if (args_has(args, 'W'))
cdata->flags |= PROMPT_WINDOW;
else if (args_has(args, 'T'))
cdata->flags |= PROMPT_TARGET;
status_prompt_set(tc, target, prompt, input,
cmd_command_prompt_callback, cmd_command_prompt_free, cdata,
cdata->flags);
free(prompt);
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
return (CMD_RETURN_NORMAL);
}
static int
cmd_command_prompt_callback(struct client *c, void *data, const char *s,
int done)
{
struct cmd_command_prompt_cdata *cdata = data;
char *error;
struct cmdq_item *item = cdata->item, *new_item;
struct cmd_list *cmdlist;
struct cmd_command_prompt_prompt *prompt;
int argc = 0;
char **argv = NULL;
struct cmd_command_prompt_cdata *cdata = data;
char *new_template, *prompt, *ptr, *error;
char *input = NULL;
enum cmd_parse_status status;
if (s == NULL)
goto out;
return (0);
if (done && (cdata->flags & PROMPT_INCREMENTAL))
return (0);
new_template = cmd_template_replace(cdata->template, s, cdata->idx);
if (done) {
if (cdata->flags & PROMPT_INCREMENTAL)
goto out;
cmd_append_argv(&cdata->argc, &cdata->argv, s);
if (++cdata->current != cdata->count) {
prompt = &cdata->prompts[cdata->current];
status_prompt_update(c, prompt->prompt, prompt->input);
return (1);
}
free(cdata->template);
cdata->template = new_template;
}
argc = cdata->argc;
argv = cmd_copy_argv(cdata->argc, cdata->argv);
if (!done)
cmd_append_argv(&argc, &argv, s);
/*
* Check if there are more prompts; if so, get its respective input
* and update the prompt data.
*/
if (done && (ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
xasprintf(&prompt, "%s ", ptr);
input = strsep(&cdata->next_input, ",");
status_prompt_update(c, prompt, input);
if (done) {
cmd_free_argv(cdata->argc, cdata->argv);
cdata->argc = argc;
cdata->argv = cmd_copy_argv(argc, argv);
free(prompt);
cdata->idx++;
return (1);
}
cmdlist = args_make_commands(cdata->state, argc, argv, &error);
if (cmdlist == NULL) {
status = cmd_parse_and_append(new_template, NULL, c, NULL, &error);
if (status == CMD_PARSE_ERROR) {
cmdq_append(c, cmdq_get_error(error));
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
cmd_free_argv(argc, argv);
if (!done)
free(new_template);
if (c->prompt_inputcb != cmd_command_prompt_callback)
return (1);
out:
if (item != NULL)
cmdq_continue(item);
return (0);
}
@ -229,14 +185,9 @@ static void
cmd_command_prompt_free(void *data)
{
struct cmd_command_prompt_cdata *cdata = data;
u_int i;
for (i = 0; i < cdata->count; i++) {
free(cdata->prompts[i].prompt);
free(cdata->prompts[i].input);
}
free(cdata->inputs);
free(cdata->prompts);
cmd_free_argv(cdata->argc, cdata->argv);
args_make_commands_free(cdata->state);
free(cdata->template);
free(cdata);
}

View File

@ -28,10 +28,8 @@
* Asks for confirmation before executing a command.
*/
static enum args_parse_type cmd_confirm_before_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_confirm_before_exec(struct cmd *,
struct cmdq_item *);
static int cmd_confirm_before_callback(struct client *, void *,
const char *, int);
@ -41,28 +39,17 @@ const struct cmd_entry cmd_confirm_before_entry = {
.name = "confirm-before",
.alias = "confirm",
.args = { "bc:p:t:y", 1, 1, cmd_confirm_before_args_parse },
.usage = "[-by] [-c confirm-key] [-p prompt] " CMD_TARGET_CLIENT_USAGE
" command",
.args = { "p:t:", 1, 1 },
.usage = "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
.flags = CMD_CLIENT_TFLAG,
.exec = cmd_confirm_before_exec
};
struct cmd_confirm_before_data {
struct cmdq_item *item;
struct cmd_list *cmdlist;
u_char confirm_key;
int default_yes;
char *cmd;
};
static enum args_parse_type
cmd_confirm_before_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static enum cmd_retval
cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
{
@ -70,51 +57,27 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_confirm_before_data *cdata;
struct client *tc = cmdq_get_target_client(item);
struct cmd_find_state *target = cmdq_get_target(item);
char *new_prompt;
const char *confirm_key, *prompt, *cmd;
int wait = !args_has(args, 'b');
cdata = xcalloc(1, sizeof *cdata);
cdata->cmdlist = args_make_commands_now(self, item, 0, 1);
if (cdata->cmdlist == NULL) {
free(cdata);
return (CMD_RETURN_ERROR);
}
if (wait)
cdata->item = item;
cdata->default_yes = args_has(args, 'y');
if ((confirm_key = args_get(args, 'c')) != NULL) {
if (confirm_key[1] == '\0' &&
confirm_key[0] > 31 &&
confirm_key[0] < 127)
cdata->confirm_key = confirm_key[0];
else {
cmdq_error(item, "invalid confirm key");
free(cdata);
return (CMD_RETURN_ERROR);
}
}
else
cdata->confirm_key = 'y';
char *cmd, *copy, *new_prompt, *ptr;
const char *prompt;
if ((prompt = args_get(args, 'p')) != NULL)
xasprintf(&new_prompt, "%s ", prompt);
else {
cmd = cmd_get_entry(cmd_list_first(cdata->cmdlist))->name;
xasprintf(&new_prompt, "Confirm '%s'? (%c/n) ", cmd,
cdata->confirm_key);
ptr = copy = xstrdup(args->argv[0]);
cmd = strsep(&ptr, " \t");
xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd);
free(copy);
}
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[0]);
status_prompt_set(tc, target, new_prompt, NULL,
cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE, PROMPT_TYPE_COMMAND);
free(new_prompt);
PROMPT_SINGLE);
if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
free(new_prompt);
return (CMD_RETURN_NORMAL);
}
static int
@ -122,34 +85,23 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s,
__unused int done)
{
struct cmd_confirm_before_data *cdata = data;
struct cmdq_item *item = cdata->item, *new_item;
int retcode = 1;
char *error;
enum cmd_parse_status status;
if (c->flags & CLIENT_DEAD)
goto out;
return (0);
if (s == NULL)
goto out;
if (s[0] != cdata->confirm_key && (s[0] != '\r' || !cdata->default_yes))
goto out;
retcode = 0;
if (s == NULL || *s == '\0')
return (0);
if (tolower((u_char)s[0]) != 'y' || s[1] != '\0')
return (0);
if (item == NULL) {
new_item = cmdq_get_command(cdata->cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cdata->cmdlist,
cmdq_get_state(item));
cmdq_insert_after(item, new_item);
status = cmd_parse_and_append(cdata->cmd, NULL, c, NULL, &error);
if (status == CMD_PARSE_ERROR) {
cmdq_append(c, cmdq_get_error(error));
free(error);
}
out:
if (item != NULL) {
if (cmdq_get_client(item) != NULL &&
cmdq_get_client(item)->session == NULL)
cmdq_get_client(item)->retval = retcode;
cmdq_continue(item);
}
return (0);
}
@ -158,6 +110,6 @@ cmd_confirm_before_free(void *data)
{
struct cmd_confirm_before_data *cdata = data;
cmd_list_free(cdata->cmdlist);
free(cdata->cmd);
free(cdata);
}

View File

@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = {
.name = "copy-mode",
.alias = NULL,
.args = { "deHMqSs:t:u", 0, 0, NULL },
.usage = "[-deHMqSu] [-s src-pane] " CMD_TARGET_PANE_USAGE,
.args = { "eHMs:t:uq", 0, 0 },
.usage = "[-eHMuq] [-s src-pane] " CMD_TARGET_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, 0 },
.target = { 't', CMD_FIND_PANE, 0 },
@ -44,7 +44,7 @@ const struct cmd_entry cmd_clock_mode_entry = {
.name = "clock-mode",
.alias = NULL,
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -91,13 +91,6 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
}
if (args_has(args, 'u'))
window_copy_pageup(wp, 0);
if (args_has(args, 'd'))
window_copy_pagedown(wp, 0, args_has(args, 'e'));
if (args_has(args, 'S')) {
window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
args_has(args, 'e'));
return (CMD_RETURN_NORMAL);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_detach_client_entry = {
.name = "detach-client",
.alias = "detach",
.args = { "aE:s:t:P", 0, 0, NULL },
.args = { "aE:s:t:P", 0, 0 },
.usage = "[-aP] [-E shell-command] "
"[-s target-session] " CMD_TARGET_CLIENT_USAGE,
@ -47,7 +47,7 @@ const struct cmd_entry cmd_suspend_client_entry = {
.name = "suspend-client",
.alias = "suspendc",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.flags = CMD_CLIENT_TFLAG,

View File

@ -27,22 +27,18 @@
* Display a menu on a client.
*/
static enum args_parse_type cmd_display_menu_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_display_menu_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_display_popup_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_display_menu_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_display_popup_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_display_menu_entry = {
.name = "display-menu",
.alias = "menu",
.args = { "b:c:C:H:s:S:MOt:T:x:y:", 1, -1, cmd_display_menu_args_parse },
.usage = "[-MO] [-b border-lines] [-c target-client] "
"[-C starting-choice] [-H selected-style] [-s style] "
"[-S border-style] " CMD_TARGET_PANE_USAGE " [-T title] "
"[-x position] [-y position] name [key] [command] ...",
.args = { "c:t:OT:x:y:", 1, -1 },
.usage = "[-O] [-c target-client] " CMD_TARGET_PANE_USAGE " [-T title] "
"[-x position] [-y position] name key command ...",
.target = { 't', CMD_FIND_PANE, 0 },
@ -54,12 +50,10 @@ const struct cmd_entry cmd_display_popup_entry = {
.name = "display-popup",
.alias = "popup",
.args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL },
.usage = "[-BCE] [-b border-lines] [-c target-client] "
"[-d start-directory] [-e environment] [-h height] "
"[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE
" [-T title] [-w width] [-x position] [-y position] "
"[shell-command [argument ...]]",
.args = { "Cc:d:Eh:t:w:x:y:", 0, -1 },
.usage = "[-CE] [-c target-client] [-d start-directory] [-h height] "
CMD_TARGET_PANE_USAGE " [-w width] "
"[-x position] [-y position] [command]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -67,30 +61,6 @@ const struct cmd_entry cmd_display_popup_entry = {
.exec = cmd_display_popup_exec
};
static enum args_parse_type
cmd_display_menu_args_parse(struct args *args, u_int idx, __unused char **cause)
{
u_int i = 0;
enum args_parse_type type = ARGS_PARSE_STRING;
for (;;) {
type = ARGS_PARSE_STRING;
if (i == idx)
break;
if (*args_string(args, i++) == '\0')
continue;
type = ARGS_PARSE_STRING;
if (i++ == idx)
break;
type = ARGS_PARSE_COMMANDS_OR_STRING;
if (i++ == idx)
break;
}
return (type);
}
static int
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
struct args *args, u_int *px, u_int *py, u_int w, u_int h)
@ -150,6 +120,8 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
if (sr != NULL)
break;
}
if (line == lines)
ranges = &tc->status.entries[0].ranges;
if (sr != NULL) {
format_add(ft, "popup_window_status_line_x", "%u",
@ -202,8 +174,8 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
} else
format_add(ft, "popup_mouse_centre_y", "%ld", n);
n = (long)event->m.y + h;
if (n >= tty->sy)
format_add(ft, "popup_mouse_top", "%u", tty->sy - 1);
if (n + h >= tty->sy)
format_add(ft, "popup_mouse_top", "%u", tty->sy - h);
else
format_add(ft, "popup_mouse_top", "%ld", n);
n = event->m.y - h;
@ -233,7 +205,7 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
if (xp == NULL || strcmp(xp, "C") == 0)
xp = "#{popup_centre_x}";
else if (strcmp(xp, "R") == 0)
xp = "#{popup_pane_right}";
xp = "#{popup_right}";
else if (strcmp(xp, "P") == 0)
xp = "#{popup_pane_left}";
else if (strcmp(xp, "M") == 0)
@ -247,7 +219,7 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
else if (n < 0)
n = 0;
*px = n;
log_debug("%s: -x: %s = %s = %u (-w %u)", __func__, xp, p, *px, w);
log_debug("%s: -x: %s = %s = %u", __func__, xp, p, *px);
free(p);
/* Expand vertical position */
@ -273,10 +245,9 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
else if (n < 0)
n = 0;
*py = n;
log_debug("%s: -y: %s = %s = %u (-h %u)", __func__, yp, p, *py, h);
log_debug("%s: -y: %s = %s = %u", __func__, yp, p, *py);
free(p);
format_free(ft);
return (1);
}
@ -289,62 +260,42 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
struct client *tc = cmdq_get_target_client(item);
struct menu *menu = NULL;
struct menu_item menu_item;
const char *key, *name, *value;
const char *style = args_get(args, 's');
const char *border_style = args_get(args, 'S');
const char *selected_style = args_get(args, 'H');
enum box_lines lines = BOX_LINES_DEFAULT;
char *title, *cause;
int flags = 0, starting_choice = 0;
u_int px, py, i, count = args_count(args);
struct options *o = target->s->curw->window->options;
struct options_entry *oe;
const char *key;
char *title, *name;
int flags = 0, i;
u_int px, py;
if (tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
if (args_has(args, 'C')) {
if (strcmp(args_get(args, 'C'), "-") == 0)
starting_choice = -1;
else {
starting_choice = args_strtonum(args, 'C', 0, UINT_MAX,
&cause);
if (cause != NULL) {
cmdq_error(item, "starting choice %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
}
if (args_has(args, 'T'))
title = format_single_from_target(item, args_get(args, 'T'));
else
title = xstrdup("");
menu = menu_create(title);
free(title);
for (i = 0; i != count; /* nothing */) {
name = args_string(args, i++);
for (i = 0; i != args->argc; /* nothing */) {
name = args->argv[i++];
if (*name == '\0') {
menu_add_item(menu, NULL, item, tc, target);
continue;
}
if (count - i < 2) {
if (args->argc - i < 2) {
cmdq_error(item, "not enough arguments");
free(title);
menu_free(menu);
return (CMD_RETURN_ERROR);
}
key = args_string(args, i++);
key = args->argv[i++];
menu_item.name = name;
menu_item.key = key_string_lookup_string(key);
menu_item.command = args_string(args, i++);
menu_item.command = args->argv[i++];
menu_add_item(menu, &menu_item, item, tc, target);
}
free(title);
if (menu == NULL) {
cmdq_error(item, "invalid menu arguments");
return (CMD_RETURN_ERROR);
@ -359,24 +310,12 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
value = args_get(args, 'b');
if (value != NULL) {
oe = options_get(o, "menu-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (lines == -1) {
cmdq_error(item, "menu-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'O'))
flags |= MENU_STAYOPEN;
if (!event->m.valid && !args_has(args, 'M'))
if (!event->m.valid)
flags |= MENU_NOMOUSE;
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
style, selected_style, border_style, target, NULL, NULL) != 0)
if (menu_display(menu, flags, item, px, py, tc, target, NULL,
NULL) != 0)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
@ -389,17 +328,11 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = target->s;
struct client *tc = cmdq_get_target_client(item);
struct tty *tty = &tc->tty;
const char *value, *shell, *shellcmd = NULL;
const char *style = args_get(args, 's');
const char *border_style = args_get(args, 'S');
char *cwd, *cause = NULL, **argv = NULL, *title;
int flags = 0, argc = 0;
enum box_lines lines = BOX_LINES_DEFAULT;
u_int px, py, w, h, count = args_count(args);
struct args_value *av;
struct environ *env = NULL;
struct options *o = s->curw->window->options;
struct options_entry *oe;
const char *value, *shell[] = { NULL, NULL };
const char *shellcmd = NULL;
char *cwd, *cause, **argv = args->argv;
int flags = 0, argc = args->argc;
u_int px, py, w, h;
if (args_has(args, 'C')) {
server_client_clear_overlay(tc);
@ -428,75 +361,37 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
}
}
if (w > tty->sx)
w = tty->sx;
if (h > tty->sy)
h = tty->sy;
if (w > tty->sx - 1)
w = tty->sx - 1;
if (h > tty->sy - 1)
h = tty->sy - 1;
if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
return (CMD_RETURN_NORMAL);
value = args_get(args, 'b');
if (args_has(args, 'B'))
lines = BOX_LINES_NONE;
else if (value != NULL) {
oe = options_get(o, "popup-border-lines");
lines = options_find_choice(options_table_entry(oe), value,
&cause);
if (cause != NULL) {
cmdq_error(item, "popup-border-lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
value = args_get(args, 'd');
if (value != NULL)
cwd = format_single_from_target(item, value);
else
cwd = xstrdup(server_client_get_cwd(tc, s));
if (count == 0)
if (argc == 0)
shellcmd = options_get_string(s->options, "default-command");
else if (count == 1)
shellcmd = args_string(args, 0);
if (count <= 1 && (shellcmd == NULL || *shellcmd == '\0')) {
else if (argc == 1)
shellcmd = argv[0];
if (argc <= 1 && (shellcmd == NULL || *shellcmd == '\0')) {
shellcmd = NULL;
shell = options_get_string(s->options, "default-shell");
if (!checkshell(shell))
shell = _PATH_BSHELL;
cmd_append_argv(&argc, &argv, shell);
} else
args_to_vector(args, &argc, &argv);
if (args_has(args, 'e') >= 1) {
env = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(env, av->string, 0);
av = args_next_value(av);
}
shell[0] = options_get_string(s->options, "default-shell");
if (!checkshell(shell[0]))
shell[0] = _PATH_BSHELL;
argc = 1;
argv = (char**)shell;
}
if (args_has(args, 'T'))
title = format_single_from_target(item, args_get(args, 'T'));
else
title = xstrdup("");
if (args_has(args, 'E') > 1)
flags |= POPUP_CLOSEEXITZERO;
else if (args_has(args, 'E'))
flags |= POPUP_CLOSEEXIT;
if (popup_display(flags, lines, item, px, py, w, h, env, shellcmd, argc,
argv, cwd, title, tc, s, style, border_style, NULL, NULL) != 0) {
cmd_free_argv(argc, argv);
if (env != NULL)
environ_free(env);
free(cwd);
free(title);
if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd,
tc, s, NULL, NULL) != 0)
return (CMD_RETURN_NORMAL);
}
if (env != NULL)
environ_free(env);
free(cwd);
free(title);
cmd_free_argv(argc, argv);
return (CMD_RETURN_WAIT);
}

View File

@ -39,8 +39,8 @@ const struct cmd_entry cmd_display_message_entry = {
.name = "display-message",
.alias = "display",
.args = { "aCc:d:lINpt:F:v", 0, 1, NULL },
.usage = "[-aCIlNpv] [-c target-client] [-d delay] [-F format] "
.args = { "acd:INpt:F:v", 0, 1 },
.usage = "[-aINpv] [-c target-client] [-d delay] [-F format] "
CMD_TARGET_PANE_USAGE " [message]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -68,28 +68,22 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
struct window_pane *wp = target->wp;
const char *template;
char *msg, *cause;
int delay = -1, flags, Nflag = args_has(args, 'N');
int Cflag = args_has(args, 'C');
int delay = -1;
struct format_tree *ft;
u_int count = args_count(args);
struct evbuffer *evb;
int flags;
if (args_has(args, 'I')) {
if (wp == NULL)
return (CMD_RETURN_NORMAL);
switch (window_pane_start_input(wp, item, &cause)) {
case -1:
if (window_pane_start_input(wp, item, &cause) != 0) {
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
case 1:
return (CMD_RETURN_NORMAL);
case 0:
return (CMD_RETURN_WAIT);
}
return (CMD_RETURN_WAIT);
}
if (args_has(args, 'F') && count != 0) {
if (args_has(args, 'F') && args->argc != 0) {
cmdq_error(item, "only one of -F or argument must be given");
return (CMD_RETURN_ERROR);
}
@ -103,10 +97,9 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
}
}
if (count != 0)
template = args_string(args, 0);
else
template = args_get(args, 'F');
template = args_get(args, 'F');
if (args->argc != 0)
template = args->argv[0];
if (template == NULL)
template = DISPLAY_MESSAGE_TEMPLATE;
@ -134,24 +127,15 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'l'))
msg = xstrdup(template);
else
msg = format_expand_time(ft, template);
msg = format_expand_time(ft, template);
if (cmdq_get_client(item) == NULL)
cmdq_error(item, "%s", msg);
else if (args_has(args, 'p'))
cmdq_print(item, "%s", msg);
else if (tc != NULL && (tc->flags & CLIENT_CONTROL)) {
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
evbuffer_add_printf(evb, "%%message %s", msg);
server_client_print(tc, 0, evb);
evbuffer_free(evb);
} else if (tc != NULL)
status_message_set(tc, delay, 0, Nflag, Cflag, "%s", msg);
else if (tc != NULL) {
status_message_set(tc, delay, 0, args_has(args, 'N'), "%s",
msg);
}
free(msg);
format_free(ft);

View File

@ -27,16 +27,14 @@
* Display panes on a client.
*/
static enum args_parse_type cmd_display_panes_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_display_panes_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_display_panes_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_display_panes_entry = {
.name = "display-panes",
.alias = "displayp",
.args = { "bd:Nt:", 0, 1, cmd_display_panes_args_parse },
.args = { "bd:Nt:", 0, 1 },
.usage = "[-bN] [-d duration] " CMD_TARGET_CLIENT_USAGE " [template]",
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
@ -44,17 +42,10 @@ const struct cmd_entry cmd_display_panes_entry = {
};
struct cmd_display_panes_data {
struct cmdq_item *item;
struct args_command_state *state;
struct cmdq_item *item;
char *command;
};
static enum args_parse_type
cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
__unused char **cause)
{
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static void
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct window_pane *wp)
@ -144,11 +135,11 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
llen = 0;
if (sx < len * 6 || sy < 5) {
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
tty_attributes(tty, &fgc, &grid_default_cell, NULL);
if (sx >= len + llen + 1) {
len += llen + 1;
tty_cursor(tty, xoff + px - len / 2, yoff + py);
tty_putn(tty, buf, len, len);
tty_putn(tty, buf, len, len);
tty_putn(tty, " ", 1, 1);
tty_putn(tty, lbuf, llen, llen);
} else {
@ -161,7 +152,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
px -= len * 3;
py -= 2;
tty_attributes(tty, &bgc, &grid_default_cell, NULL, NULL);
tty_attributes(tty, &bgc, &grid_default_cell, NULL);
for (ptr = buf; *ptr != '\0'; ptr++) {
if (*ptr < '0' || *ptr > '9')
continue;
@ -179,7 +170,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
if (sy <= 6)
goto out;
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
tty_attributes(tty, &fgc, &grid_default_cell, NULL);
if (rlen != 0 && sx >= rlen) {
tty_cursor(tty, xoff + sx - rlen, yoff);
tty_putn(tty, rbuf, rlen, rlen);
@ -195,8 +186,7 @@ out:
}
static void
cmd_display_panes_draw(struct client *c, __unused void *data,
struct screen_redraw_ctx *ctx)
cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
@ -210,25 +200,24 @@ cmd_display_panes_draw(struct client *c, __unused void *data,
}
static void
cmd_display_panes_free(__unused struct client *c, void *data)
cmd_display_panes_free(struct client *c)
{
struct cmd_display_panes_data *cdata = data;
struct cmd_display_panes_data *cdata = c->overlay_data;
if (cdata->item != NULL)
cmdq_continue(cdata->item);
args_make_commands_free(cdata->state);
free(cdata->command);
free(cdata);
}
static int
cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
cmd_display_panes_key(struct client *c, struct key_event *event)
{
struct cmd_display_panes_data *cdata = data;
char *expanded, *error;
struct cmdq_item *item = cdata->item, *new_item;
struct cmd_list *cmdlist;
struct cmd_display_panes_data *cdata = c->overlay_data;
char *cmd, *expanded, *error;
struct window *w = c->session->curw->window;
struct window_pane *wp;
enum cmd_parse_status status;
u_int index;
key_code key;
@ -246,22 +235,18 @@ cmd_display_panes_key(struct client *c, void *data, struct key_event *event)
wp = window_pane_at_index(w, index);
if (wp == NULL)
return (1);
window_unzoom(w, 1);
window_unzoom(w);
xasprintf(&expanded, "%%%u", wp->id);
cmd = cmd_template_replace(cdata->command, expanded, 1);
cmdlist = args_make_commands(cdata->state, 1, &expanded, &error);
if (cmdlist == NULL) {
status = cmd_parse_and_append(cmd, NULL, c, NULL, &error);
if (status == CMD_PARSE_ERROR) {
cmdq_append(c, cmdq_get_error(error));
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
free(cmd);
free(expanded);
return (1);
}
@ -272,10 +257,9 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct session *s = tc->session;
u_int delay;
u_int delay;
char *cause;
struct cmd_display_panes_data *cdata;
int wait = !args_has(args, 'b');
if (tc->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
@ -290,23 +274,27 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
} else
delay = options_get_number(s->options, "display-panes-time");
cdata = xcalloc(1, sizeof *cdata);
if (wait)
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->command = xstrdup(args->argv[0]);
else
cdata->command = xstrdup("select-pane -t '%%'");
if (args_has(args, 'b'))
cdata->item = NULL;
else
cdata->item = item;
cdata->state = args_make_commands_prepare(self, item, 0,
"select-pane -t \"%%%\"", wait, 0);
if (args_has(args, 'N')) {
server_client_set_overlay(tc, delay, NULL, NULL,
cmd_display_panes_draw, NULL, cmd_display_panes_free, NULL,
cmd_display_panes_draw, NULL, cmd_display_panes_free,
cdata);
} else {
server_client_set_overlay(tc, delay, NULL, NULL,
cmd_display_panes_draw, cmd_display_panes_key,
cmd_display_panes_free, NULL, cdata);
cmd_display_panes_free, cdata);
}
if (!wait)
if (args_has(args, 'b'))
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_find_window_entry = {
.name = "find-window",
.alias = "findw",
.args = { "CiNrt:TZ", 1, 1, NULL },
.args = { "CiNrt:TZ", 1, 1 },
.usage = "[-CiNrTZ] " CMD_TARGET_PANE_USAGE " match-string",
.target = { 't', CMD_FIND_PANE, 0 },
@ -47,17 +47,14 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self), *new_args;
struct cmd_find_state *target = cmdq_get_target(item);
struct window_pane *wp = target->wp;
const char *s = args_string(args, 0), *suffix = "";
const char *star = "*";
struct args_value *filter;
const char *s = args->argv[0], *suffix = "";
char *filter, *argv = { NULL };
int C, N, T;
C = args_has(args, 'C');
N = args_has(args, 'N');
T = args_has(args, 'T');
if (args_has(args, 'r'))
star = "";
if (args_has(args, 'r') && args_has(args, 'i'))
suffix = "/ri";
else if (args_has(args, 'r'))
@ -68,49 +65,41 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
if (!C && !N && !T)
C = N = T = 1;
filter = xcalloc(1, sizeof *filter);
filter->type = ARGS_STRING;
if (C && N && T) {
xasprintf(&filter->string,
xasprintf(&filter,
"#{||:"
"#{C%s:%s},#{||:#{m%s:%s%s%s,#{window_name}},"
"#{m%s:%s%s%s,#{pane_title}}}}",
suffix, s, suffix, star, s, star, suffix, star, s, star);
"#{C%s:%s},#{||:#{m%s:*%s*,#{window_name}},"
"#{m%s:*%s*,#{pane_title}}}}",
suffix, s, suffix, s, suffix, s);
} else if (C && N) {
xasprintf(&filter->string,
"#{||:#{C%s:%s},#{m%s:%s%s%s,#{window_name}}}",
suffix, s, suffix, star, s, star);
xasprintf(&filter,
"#{||:#{C%s:%s},#{m%s:*%s*,#{window_name}}}",
suffix, s, suffix, s);
} else if (C && T) {
xasprintf(&filter->string,
"#{||:#{C%s:%s},#{m%s:%s%s%s,#{pane_title}}}",
suffix, s, suffix, star, s, star);
xasprintf(&filter,
"#{||:#{C%s:%s},#{m%s:*%s*,#{pane_title}}}",
suffix, s, suffix, s);
} else if (N && T) {
xasprintf(&filter->string,
"#{||:#{m%s:%s%s%s,#{window_name}},"
"#{m%s:%s%s%s,#{pane_title}}}",
suffix, star, s, star, suffix, star, s, star);
} else if (C) {
xasprintf(&filter->string,
"#{C%s:%s}",
suffix, s);
} else if (N) {
xasprintf(&filter->string,
"#{m%s:%s%s%s,#{window_name}}",
suffix, star, s, star);
} else {
xasprintf(&filter->string,
"#{m%s:%s%s%s,#{pane_title}}",
suffix, star, s, star);
}
xasprintf(&filter,
"#{||:#{m%s:*%s*,#{window_name}},"
"#{m%s:*%s*,#{pane_title}}}",
suffix, s, suffix, s);
} else if (C)
xasprintf(&filter, "#{C%s:%s}", suffix, s);
else if (N)
xasprintf(&filter, "#{m%s:*%s*,#{window_name}}", suffix, s);
else
xasprintf(&filter, "#{m%s:*%s*,#{pane_title}}", suffix, s);
new_args = args_create();
new_args = args_parse("", 1, &argv);
if (args_has(args, 'Z'))
args_set(new_args, 'Z', NULL, 0);
args_set(new_args, 'f', filter, 0);
args_set(new_args, 'Z', NULL);
args_set(new_args, 'f', filter);
window_pane_set_mode(wp, NULL, &window_tree_mode, target, new_args);
args_free(new_args);
free(filter);
return (CMD_RETURN_NORMAL);
}

View File

@ -582,27 +582,27 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane)
/* Try special characters. */
if (strcmp(pane, "!") == 0) {
fs->wp = TAILQ_FIRST(&fs->w->last_panes);
fs->wp = fs->w->last;
if (fs->wp == NULL)
return (-1);
return (0);
} else if (strcmp(pane, "{up-of}") == 0) {
fs->wp = window_pane_find_up(fs->w->active);
fs->wp = window_pane_find_up(fs->current->wp);
if (fs->wp == NULL)
return (-1);
return (0);
} else if (strcmp(pane, "{down-of}") == 0) {
fs->wp = window_pane_find_down(fs->w->active);
fs->wp = window_pane_find_down(fs->current->wp);
if (fs->wp == NULL)
return (-1);
return (0);
} else if (strcmp(pane, "{left-of}") == 0) {
fs->wp = window_pane_find_left(fs->w->active);
fs->wp = window_pane_find_left(fs->current->wp);
if (fs->wp == NULL)
return (-1);
return (0);
} else if (strcmp(pane, "{right-of}") == 0) {
fs->wp = window_pane_find_right(fs->w->active);
fs->wp = window_pane_find_right(fs->current->wp);
if (fs->wp == NULL)
return (-1);
return (0);
@ -614,7 +614,7 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane)
n = strtonum(pane + 1, 1, INT_MAX, NULL);
else
n = 1;
wp = fs->w->active;
wp = fs->current->wp;
if (pane[0] == '+')
fs->wp = window_pane_next_by_number(fs->w, wp, n);
else

View File

@ -20,7 +20,6 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@ -30,19 +29,16 @@
* Executes a tmux command if a shell command returns true or false.
*/
static enum args_parse_type cmd_if_shell_args_parse(struct args *, u_int,
char **);
static enum cmd_retval cmd_if_shell_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmdq_item *);
static void cmd_if_shell_callback(struct job *);
static void cmd_if_shell_free(void *);
static void cmd_if_shell_callback(struct job *);
static void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
.name = "if-shell",
.alias = "if",
.args = { "bFt:", 2, 3, cmd_if_shell_args_parse },
.args = { "bFt:", 2, 3 },
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
"[command]",
@ -53,72 +49,86 @@ const struct cmd_entry cmd_if_shell_entry = {
};
struct cmd_if_shell_data {
struct args_command_state *cmd_if;
struct args_command_state *cmd_else;
struct cmd_parse_input input;
struct client *client;
struct cmdq_item *item;
char *cmd_if;
char *cmd_else;
struct client *client;
struct cmdq_item *item;
};
static enum args_parse_type
cmd_if_shell_args_parse(__unused struct args *args, u_int idx,
__unused char **cause)
{
if (idx == 1 || idx == 2)
return (ARGS_PARSE_COMMANDS_OR_STRING);
return (ARGS_PARSE_STRING);
}
static enum cmd_retval
cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct cmdq_state *state = cmdq_get_state(item);
struct cmd_if_shell_data *cdata;
struct cmdq_item *new_item;
char *shellcmd;
char *shellcmd, *cmd, *error;
const char *file;
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct cmd_list *cmdlist;
u_int count = args_count(args);
int wait = !args_has(args, 'b');
struct cmd_parse_input pi;
enum cmd_parse_status status;
shellcmd = format_single_from_target(item, args_string(args, 0));
shellcmd = format_single_from_target(item, args->argv[0]);
if (args_has(args, 'F')) {
if (*shellcmd != '0' && *shellcmd != '\0')
cmdlist = args_make_commands_now(self, item, 1, 0);
else if (count == 3)
cmdlist = args_make_commands_now(self, item, 2, 0);
else {
free(shellcmd);
return (CMD_RETURN_NORMAL);
}
cmd = args->argv[1];
else if (args->argc == 3)
cmd = args->argv[2];
else
cmd = NULL;
free(shellcmd);
if (cmdlist == NULL)
if (cmd == NULL)
return (CMD_RETURN_NORMAL);
memset(&pi, 0, sizeof pi);
cmd_get_source(self, &pi.file, &pi.line);
pi.item = item;
pi.c = tc;
cmd_find_copy_state(&pi.fs, target);
status = cmd_parse_and_insert(cmd, &pi, item, state, &error);
if (status == CMD_PARSE_ERROR) {
cmdq_error(item, "%s", error);
free(error);
return (CMD_RETURN_ERROR);
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
}
return (CMD_RETURN_NORMAL);
}
cdata = xcalloc(1, sizeof *cdata);
cdata->cmd_if = args_make_commands_prepare(self, item, 1, NULL, wait,
0);
if (count == 3) {
cdata->cmd_else = args_make_commands_prepare(self, item, 2,
NULL, wait, 0);
}
cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
cdata->cmd_else = xstrdup(args->argv[2]);
else
cdata->cmd_else = NULL;
if (wait) {
if (!args_has(args, 'b'))
cdata->client = cmdq_get_client(item);
cdata->item = item;
} else
else
cdata->client = tc;
if (cdata->client != NULL)
cdata->client->references++;
if (job_run(shellcmd, 0, NULL, NULL, s,
if (!args_has(args, 'b'))
cdata->item = item;
else
cdata->item = NULL;
memset(&cdata->input, 0, sizeof cdata->input);
cmd_get_source(self, &file, &cdata->input.line);
if (file != NULL)
cdata->input.file = xstrdup(file);
cdata->input.c = tc;
if (cdata->input.c != NULL)
cdata->input.c->references++;
cmd_find_copy_state(&cdata->input.fs, target);
if (job_run(shellcmd, 0, NULL, s,
server_client_get_cwd(cmdq_get_client(item), s), NULL,
cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1,
-1) == NULL) {
@ -129,7 +139,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
}
free(shellcmd);
if (!wait)
if (args_has(args, 'b'))
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
@ -139,34 +149,45 @@ cmd_if_shell_callback(struct job *job)
{
struct cmd_if_shell_data *cdata = job_get_data(job);
struct client *c = cdata->client;
struct cmdq_item *item = cdata->item, *new_item;
struct args_command_state *state;
struct cmd_list *cmdlist;
char *error;
struct cmdq_item *new_item = NULL;
struct cmdq_state *new_state = NULL;
char *cmd;
int status;
struct cmd_parse_result *pr;
status = job_get_status(job);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
state = cdata->cmd_else;
cmd = cdata->cmd_else;
else
state = cdata->cmd_if;
if (state == NULL)
cmd = cdata->cmd_if;
if (cmd == NULL)
goto out;
cmdlist = args_make_commands(state, 0, NULL, &error);
if (cmdlist == NULL) {
if (cdata->item == NULL) {
*error = toupper((u_char)*error);
status_message_set(c, -1, 1, 0, 0, "%s", error);
} else
cmdq_error(cdata->item, "%s", error);
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
pr = cmd_parse_from_string(cmd, &cdata->input);
switch (pr->status) {
case CMD_PARSE_EMPTY:
break;
case CMD_PARSE_ERROR:
if (cdata->item != NULL)
cmdq_error(cdata->item, "%s", pr->error);
free(pr->error);
break;
case CMD_PARSE_SUCCESS:
if (cdata->item == NULL)
new_state = cmdq_new_state(NULL, NULL, 0);
else
new_state = cmdq_get_state(cdata->item);
new_item = cmdq_get_command(pr->cmdlist, new_state);
if (cdata->item == NULL)
cmdq_free_state(new_state);
cmd_list_free(pr->cmdlist);
break;
}
if (new_item != NULL) {
if (cdata->item == NULL)
cmdq_append(c, new_item);
else
cmdq_insert_after(cdata->item, new_item);
}
out:
@ -182,9 +203,12 @@ cmd_if_shell_free(void *data)
if (cdata->client != NULL)
server_client_unref(cdata->client);
if (cdata->cmd_else != NULL)
args_make_commands_free(cdata->cmd_else);
args_make_commands_free(cdata->cmd_if);
free(cdata->cmd_else);
free(cdata->cmd_if);
if (cdata->input.c != NULL)
server_client_unref(cdata->input.c);
free((void *)cdata->input.file);
free(cdata);
}

View File

@ -35,7 +35,7 @@ const struct cmd_entry cmd_join_pane_entry = {
.name = "join-pane",
.alias = "joinp",
.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
.args = { "bdfhvp:l:s:t:", 0, 0 },
.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
@ -49,7 +49,7 @@ const struct cmd_entry cmd_move_pane_entry = {
.name = "move-pane",
.alias = "movep",
.args = { "bdfhvp:l:s:t:", 0, 0, NULL },
.args = { "bdfhvp:l:s:t:", 0, 0 },
.usage = "[-bdfhv] [-l size] " CMD_SRCDST_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
@ -71,11 +71,10 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
struct window *src_w, *dst_w;
struct window_pane *src_wp, *dst_wp;
char *cause = NULL;
int size, dst_idx;
int size, percentage, dst_idx;
int flags;
enum layout_type type;
struct layout_cell *lc;
u_int curval = 0;
dst_s = target->s;
dst_wl = target->wl;
@ -98,30 +97,23 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = dst_w->sy;
else
curval = dst_w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = dst_wp->sy;
else
curval = dst_wp->sx;
}
}
size = -1;
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, &cause);
if (type == LAYOUT_TOPBOTTOM) {
size = args_percentage(args, 'l', 0, INT_MAX,
dst_wp->sy, &cause);
} else {
size = args_percentage(args, 'l', 0, INT_MAX,
dst_wp->sx, &cause);
}
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'l', 0, 100, item,
&cause);
if (cause == NULL)
size = curval * size / 100;
percentage = args_strtonum(args, 'p', 0, 100, &cause);
if (cause == NULL) {
if (type == LAYOUT_TOPBOTTOM)
size = (dst_wp->sy * percentage) / 100;
else
size = (dst_wp->sx * percentage) / 100;
}
}
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
@ -149,13 +141,12 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
src_wp->flags |= PANE_STYLECHANGED;
if (flags & SPAWN_BEFORE)
TAILQ_INSERT_BEFORE(dst_wp, src_wp, entry);
else
TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
layout_assign_pane(lc, src_wp, 0);
colour_palette_from_option(&src_wp->palette, src_wp->options);
recalculate_sizes();

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_kill_pane_entry = {
.name = "kill-pane",
.alias = "killp",
.args = { "at:", 0, 0, NULL },
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_kill_server_entry = {
.name = "kill-server",
.alias = NULL,
.args = { "", 0, 0, NULL },
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
@ -44,7 +44,7 @@ const struct cmd_entry cmd_start_server_entry = {
.name = "start-server",
.alias = "start",
.args = { "", 0, 0, NULL },
.args = { "", 0, 0 },
.usage = "",
.flags = CMD_STARTSERVER,

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_kill_session_entry = {
.name = "kill-session",
.alias = NULL,
.args = { "aCt:", 0, 0, NULL },
.args = { "aCt:", 0, 0 },
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },

View File

@ -30,7 +30,7 @@ const struct cmd_entry cmd_kill_window_entry = {
.name = "kill-window",
.alias = "killw",
.args = { "at:", 0, 0, NULL },
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -43,7 +43,7 @@ const struct cmd_entry cmd_unlink_window_entry = {
.name = "unlink-window",
.alias = "unlinkw",
.args = { "kt:", 0, 0, NULL },
.args = { "kt:", 0, 0 },
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },

View File

@ -36,7 +36,7 @@ const struct cmd_entry cmd_list_buffers_entry = {
.name = "list-buffers",
.alias = "lsb",
.args = { "F:f:", 0, 0, NULL },
.args = { "F:f:", 0, 0 },
.usage = "[-F format] [-f filter]",
.flags = CMD_AFTERHOOK,

View File

@ -31,8 +31,6 @@
#define LIST_CLIENTS_TEMPLATE \
"#{client_name}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}] " \
"#{?#{!=:#{client_uid},#{uid}}," \
"[user #{?client_user,#{client_user},#{client_uid},}] ,}" \
"#{?client_flags,(,}#{client_flags}#{?client_flags,),}"
static enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmdq_item *);
@ -41,8 +39,8 @@ const struct cmd_entry cmd_list_clients_entry = {
.name = "list-clients",
.alias = "lsc",
.args = { "F:f:t:", 0, 0, NULL },
.usage = "[-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
.args = { "F:t:", 0, 0 },
.usage = "[-F format] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -58,10 +56,9 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
struct client *c;
struct session *s;
struct format_tree *ft;
const char *template, *filter;
const char *template;
u_int idx;
char *line, *expanded;
int flag;
char *line;
if (args_has(args, 't'))
s = target->s;
@ -70,7 +67,6 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
if ((template = args_get(args, 'F')) == NULL)
template = LIST_CLIENTS_TEMPLATE;
filter = args_get(args, 'f');
idx = 0;
TAILQ_FOREACH(c, &clients, entry) {
@ -81,17 +77,9 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
format_add(ft, "line", "%u", idx);
format_defaults(ft, c, NULL, NULL, NULL);
if (filter != NULL) {
expanded = format_expand(ft, filter);
flag = format_true(expanded);
free(expanded);
} else
flag = 1;
if (flag) {
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
}
line = format_expand(ft, template);
cmdq_print(item, "%s", line);
free(line);
format_free(ft);

View File

@ -36,7 +36,7 @@ const struct cmd_entry cmd_list_keys_entry = {
.name = "list-keys",
.alias = "lsk",
.args = { "1aNP:T:", 0, 1, NULL },
.args = { "1aNP:T:", 0, 1 },
.usage = "[-1aN] [-P prefix-string] [-T key-table] [key]",
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
@ -47,7 +47,7 @@ const struct cmd_entry cmd_list_commands_entry = {
.name = "list-commands",
.alias = "lscm",
.args = { "F:", 0, 1, NULL },
.args = { "F:", 0, 1 },
.usage = "[-F format] [command]",
.flags = CMD_STARTSERVER|CMD_AFTERHOOK,
@ -91,7 +91,7 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
struct key_binding *bd;
const char *key;
char *tmp, *note;
int found = 0;
int found = 0;
table = key_bindings_get_table(tablename, 0);
if (table == NULL)
@ -114,8 +114,8 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
note = xstrdup(bd->note);
tmp = utf8_padcstr(key, keywidth + 1);
if (args_has(args, '1') && tc != NULL) {
status_message_set(tc, -1, 1, 0, 0, "%s%s%s", prefix,
tmp, note);
status_message_set(tc, -1, 1, 0, "%s%s%s", prefix, tmp,
note);
} else
cmdq_print(item, "%s%s%s", prefix, tmp, note);
free(tmp);
@ -148,10 +148,9 @@ static enum cmd_retval
cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
struct key_table *table;
struct key_binding *bd;
const char *tablename, *r, *keystr;
const char *tablename, *r;
char *key, *cp, *tmp, *start, *empty;
key_code prefix, only = KEYC_UNKNOWN;
int repeat, width, tablewidth, keywidth, found = 0;
@ -160,13 +159,13 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
if (cmd_get_entry(self) == &cmd_list_commands_entry)
return (cmd_list_keys_commands(self, item));
if ((keystr = args_string(args, 0)) != NULL) {
only = key_string_lookup_string(keystr);
if (args->argc != 0) {
only = key_string_lookup_string(args->argv[0]);
if (only == KEYC_UNKNOWN) {
cmdq_error(item, "invalid key: %s", keystr);
cmdq_error(item, "invalid key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
only &= KEYC_MASK_KEY;
}
tablename = args_get(args, 'T');
@ -212,7 +211,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
repeat = 0;
tablewidth = keywidth = 0;
table = key_bindings_first_table();
table = key_bindings_first_table ();
while (table != NULL) {
if (tablename != NULL && strcmp(table->name, tablename) != 0) {
table = key_bindings_next_table(table);
@ -245,7 +244,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
tmpsize = 256;
tmp = xmalloc(tmpsize);
table = key_bindings_first_table();
table = key_bindings_first_table ();
while (table != NULL) {
if (tablename != NULL && strcmp(table->name, tablename) != 0) {
table = key_bindings_next_table(table);
@ -297,15 +296,9 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
strlcat(tmp, cp, tmpsize);
free(cp);
if (args_has(args, '1') && tc != NULL) {
status_message_set(tc, -1, 1, 0, 0,
"bind-key %s", tmp);
} else
cmdq_print(item, "bind-key %s", tmp);
free(key);
cmdq_print(item, "bind-key %s", tmp);
if (args_has(args, '1'))
break;
free(key);
bd = key_bindings_next(table, bd);
}
table = key_bindings_next_table(table);
@ -315,37 +308,12 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
out:
if (only != KEYC_UNKNOWN && !found) {
cmdq_error(item, "unknown key: %s", args_string(args, 0));
cmdq_error(item, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
static void
cmd_list_single_command(const struct cmd_entry *entry, struct format_tree *ft,
const char *template, struct cmdq_item *item)
{
const char *s;
char *line;
format_add(ft, "command_list_name", "%s", entry->name);
if (entry->alias != NULL)
s = entry->alias;
else
s = "";
format_add(ft, "command_list_alias", "%s", s);
if (entry->usage != NULL)
s = entry->usage;
else
s = "";
format_add(ft, "command_list_usage", "%s", s);
line = format_expand(ft, template);
if (*line != '\0')
cmdq_print(item, "%s", line);
free(line);
}
static enum cmd_retval
cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
{
@ -353,8 +321,11 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
const struct cmd_entry **entryp;
const struct cmd_entry *entry;
struct format_tree *ft;
const char *template, *command;
char *cause;
const char *template, *s, *command = NULL;
char *line;
if (args->argc != 0)
command = args->argv[0];
if ((template = args_get(args, 'F')) == NULL) {
template = "#{command_list_name}"
@ -365,20 +336,30 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_defaults(ft, NULL, NULL, NULL, NULL);
command = args_string(args, 0);
if (command == NULL) {
for (entryp = cmd_table; *entryp != NULL; entryp++)
cmd_list_single_command(*entryp, ft, template, item);
} else {
entry = cmd_find(command, &cause);
if (entry != NULL)
cmd_list_single_command(entry, ft, template, item);
else {
cmdq_error(item, "%s", cause);
free(cause);
format_free(ft);
return (CMD_RETURN_ERROR);
}
for (entryp = cmd_table; *entryp != NULL; entryp++) {
entry = *entryp;
if (command != NULL &&
(strcmp(entry->name, command) != 0 &&
(entry->alias == NULL ||
strcmp(entry->alias, command) != 0)))
continue;
format_add(ft, "command_list_name", "%s", entry->name);
if (entry->alias != NULL)
s = entry->alias;
else
s = "";
format_add(ft, "command_list_alias", "%s", s);
if (entry->usage != NULL)
s = entry->usage;
else
s = "";
format_add(ft, "command_list_usage", "%s", s);
line = format_expand(ft, template);
if (*line != '\0')
cmdq_print(item, "%s", line);
free(line);
}
format_free(ft);

View File

@ -38,7 +38,7 @@ const struct cmd_entry cmd_list_panes_entry = {
.name = "list-panes",
.alias = "lsp",
.args = { "asF:f:t:", 0, 0, NULL },
.args = { "asF:f:t:", 0, 0 },
.usage = "[-as] [-F format] [-f filter] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },

View File

@ -42,7 +42,7 @@ const struct cmd_entry cmd_list_sessions_entry = {
.name = "list-sessions",
.alias = "ls",
.args = { "F:f:", 0, 0, NULL },
.args = { "F:f:", 0, 0 },
.usage = "[-F format] [-f filter]",
.flags = CMD_AFTERHOOK,

View File

@ -49,7 +49,7 @@ const struct cmd_entry cmd_list_windows_entry = {
.name = "list-windows",
.alias = "lsw",
.args = { "F:f:at:", 0, 0, NULL },
.args = { "F:f:at:", 0, 0 },
.usage = "[-a] [-F format] [-f filter] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },

View File

@ -37,7 +37,7 @@ const struct cmd_entry cmd_load_buffer_entry = {
.name = "load-buffer",
.alias = "loadb",
.args = { "b:t:w", 1, 1, NULL },
.args = { "b:t:w", 1, 1 },
.usage = CMD_BUFFER_USAGE " " CMD_TARGET_CLIENT_USAGE " path",
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL,
@ -77,7 +77,7 @@ cmd_load_buffer_done(__unused struct client *c, const char *path, int error,
} else if (tc != NULL &&
tc->session != NULL &&
(~tc->flags & CLIENT_DEAD))
tty_set_selection(&tc->tty, "", copy, bsize);
tty_set_selection(&tc->tty, copy, bsize);
if (tc != NULL)
server_client_unref(tc);
}
@ -105,7 +105,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
cdata->client->references++;
}
path = format_single_from_target(item, args_string(args, 0));
path = format_single_from_target(item, args->argv[0]);
file_read(cmdq_get_client(item), path, cmd_load_buffer_done, cdata);
free(path);

View File

@ -30,7 +30,7 @@ const struct cmd_entry cmd_lock_server_entry = {
.name = "lock-server",
.alias = "lock",
.args = { "", 0, 0, NULL },
.args = { "", 0, 0 },
.usage = "",
.flags = CMD_AFTERHOOK,
@ -41,7 +41,7 @@ const struct cmd_entry cmd_lock_session_entry = {
.name = "lock-session",
.alias = "locks",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -54,7 +54,7 @@ const struct cmd_entry cmd_lock_client_entry = {
.name = "lock-client",
.alias = "lockc",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_move_window_entry = {
.name = "move-window",
.alias = "movew",
.args = { "abdkrs:t:", 0, 0, NULL },
.args = { "abdkrs:t:", 0, 0 },
.usage = "[-abdkr] " CMD_SRCDST_WINDOW_USAGE,
.source = { 's', CMD_FIND_WINDOW, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_link_window_entry = {
.name = "link-window",
.alias = "linkw",
.args = { "abdks:t:", 0, 0, NULL },
.args = { "abdks:t:", 0, 0 },
.usage = "[-abdk] " CMD_SRCDST_WINDOW_USAGE,
.source = { 's', CMD_FIND_WINDOW, 0 },

View File

@ -39,11 +39,10 @@ const struct cmd_entry cmd_new_session_entry = {
.name = "new-session",
.alias = "new",
.args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1, NULL },
.args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1 },
.usage = "[-AdDEPX] [-c start-directory] [-e environment] [-F format] "
"[-f flags] [-n window-name] [-s session-name] "
CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
"[shell-command [argument ...]]",
CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@ -55,7 +54,7 @@ const struct cmd_entry cmd_has_session_entry = {
.name = "has-session",
.alias = "has",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -76,15 +75,15 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
struct options *oo;
struct termios tio, *tiop;
struct session_group *sg = NULL;
const char *errstr, *template, *group, *tmp;
const char *errstr, *template, *group, *tmp, *add;
char *cause, *cwd = NULL, *cp, *newname = NULL;
char *name, *prefix = NULL;
int detached, already_attached, is_control = 0;
u_int sx, sy, dsx, dsy, count = args_count(args);
struct spawn_context sc = { 0 };
u_int sx, sy, dsx, dsy;
struct spawn_context sc;
enum cmd_retval retval;
struct cmd_find_state fs;
struct args_value *av;
struct args_value *value;
if (cmd_get_entry(self) == &cmd_has_session_entry) {
/*
@ -94,7 +93,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 't') && (count != 0 || args_has(args, 'n'))) {
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
cmdq_error(item, "command or window name given with target");
return (CMD_RETURN_ERROR);
}
@ -103,11 +102,6 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
if (tmp != NULL) {
name = format_single(item, tmp, c, NULL, NULL, NULL);
newname = session_check_name(name);
if (newname == NULL) {
cmdq_error(item, "invalid session: %s", name);
free(name);
return (CMD_RETURN_ERROR);
}
free(name);
}
if (args_has(args, 'A')) {
@ -140,14 +134,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
prefix = xstrdup(sg->name);
else if (groupwith != NULL)
prefix = xstrdup(groupwith->name);
else {
else
prefix = session_check_name(group);
if (prefix == NULL) {
cmdq_error(item, "invalid session group: %s",
group);
goto fail;
}
}
}
/* Set -d if no client. */
@ -270,21 +258,21 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
env = environ_create();
if (c != NULL && !args_has(args, 'E'))
environ_update(global_s_options, c->environ, env);
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(env, av->string, 0);
av = args_next_value(av);
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(env, add, 0);
add = args_next_value(&value);
}
s = session_create(prefix, newname, cwd, env, oo, tiop);
/* Spawn the initial window. */
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
if (!detached)
sc.tc = c;
sc.name = args_get(args, 'n');
args_to_vector(args, &sc.argc, &sc.argv);
sc.argc = args->argc;
sc.argv = args->argv;
sc.idx = -1;
sc.cwd = args_get(args, 'c');
@ -328,10 +316,25 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
} else if (c->session != NULL)
c->last_session = c->session;
server_client_set_session(c, s);
c->session = s;
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
server_client_set_key_table(c, NULL);
tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
}
recalculate_sizes();
server_update_socket();
/*
* If there are still configuration file errors to display, put the new
* session's current window into more mode and display them now.
*/
if (cfg_finished)
cfg_show_causes(s);
/* Print if requested. */
if (args_has(args, 'P')) {
@ -350,19 +353,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
cmd_find_from_session(&fs, s, 0);
cmdq_insert_hook(s, item, &fs, "after-new-session");
if (cfg_finished)
cfg_show_causes(s);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
free(cwd);
free(newname);
free(prefix);
return (CMD_RETURN_NORMAL);
fail:
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
free(cwd);
free(newname);
free(prefix);

View File

@ -38,10 +38,9 @@ const struct cmd_entry cmd_new_window_entry = {
.name = "new-window",
.alias = "neww",
.args = { "abc:de:F:kn:PSt:", 0, -1, NULL },
.args = { "abc:de:F:kn:PSt:", 0, -1 },
.usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
"[-n window-name] " CMD_TARGET_WINDOW_USAGE
" [shell-command [argument ...]]",
"[-n window-name] " CMD_TARGET_WINDOW_USAGE " [command]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
@ -56,15 +55,16 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
struct client *c = cmdq_get_client(item);
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct spawn_context sc = { 0 };
struct spawn_context sc;
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl, *new_wl = NULL;
struct winlink *wl = target->wl;
int idx = target->idx, before;
char *cause = NULL, *cp, *expanded;
const char *template, *name;
struct winlink *new_wl = NULL;
char *cause = NULL, *cp;
const char *template, *add, *name;
struct cmd_find_state fs;
struct args_value *av;
struct args_value *value;
/*
* If -S and -n are given and -t is not and a single window with this
@ -72,19 +72,16 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
*/
name = args_get(args, 'n');
if (args_has(args, 'S') && name != NULL && target->idx == -1) {
expanded = format_single(item, name, c, s, NULL, NULL);
RB_FOREACH(wl, winlinks, &s->windows) {
if (strcmp(wl->window->name, expanded) != 0)
if (strcmp(wl->window->name, name) != 0)
continue;
if (new_wl == NULL) {
new_wl = wl;
continue;
}
cmdq_error(item, "multiple windows named %s", name);
free(expanded);
return (CMD_RETURN_ERROR);
}
free(expanded);
if (new_wl != NULL) {
if (args_has(args, 'd'))
return (CMD_RETURN_NORMAL);
@ -97,6 +94,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
}
}
before = args_has(args, 'b');
if (args_has(args, 'a') || before) {
idx = winlink_shuffle_up(s, wl, before);
@ -104,18 +102,20 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
idx = target->idx;
}
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.tc = tc;
sc.name = args_get(args, 'n');
args_to_vector(args, &sc.argc, &sc.argv);
sc.argc = args->argc;
sc.argv = args->argv;
sc.environ = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add, 0);
add = args_next_value(&value);
}
sc.idx = idx;
@ -130,9 +130,6 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
if ((new_wl = spawn_window(&sc, &cause)) == NULL) {
cmdq_error(item, "create window failed: %s", cause);
free(cause);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
if (!args_has(args, 'd') || new_wl == s->curw) {
@ -153,8 +150,6 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
cmd_find_from_winlink(&fs, new_wl, 0);
cmdq_insert_hook(s, item, &fs, "after-new-window");
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_NORMAL);
}

View File

@ -42,27 +42,13 @@ struct cmd_parse_scope {
TAILQ_ENTRY (cmd_parse_scope) entry;
};
enum cmd_parse_argument_type {
CMD_PARSE_STRING,
CMD_PARSE_COMMANDS,
CMD_PARSE_PARSED_COMMANDS
};
struct cmd_parse_argument {
enum cmd_parse_argument_type type;
char *string;
struct cmd_parse_commands *commands;
struct cmd_list *cmdlist;
TAILQ_ENTRY(cmd_parse_argument) entry;
};
TAILQ_HEAD(cmd_parse_arguments, cmd_parse_argument);
struct cmd_parse_command {
u_int line;
struct cmd_parse_arguments arguments;
u_int line;
TAILQ_ENTRY(cmd_parse_command) entry;
int argc;
char **argv;
TAILQ_ENTRY(cmd_parse_command) entry;
};
TAILQ_HEAD(cmd_parse_commands, cmd_parse_command);
@ -91,9 +77,8 @@ static char *cmd_parse_get_error(const char *, u_int, const char *);
static void cmd_parse_free_command(struct cmd_parse_command *);
static struct cmd_parse_commands *cmd_parse_new_commands(void);
static void cmd_parse_free_commands(struct cmd_parse_commands *);
static void cmd_parse_build_commands(struct cmd_parse_commands *,
struct cmd_parse_input *, struct cmd_parse_result *);
static void cmd_parse_print_commands(struct cmd_parse_input *,
static char *cmd_parse_commands_to_string(struct cmd_parse_commands *);
static void cmd_parse_print_commands(struct cmd_parse_input *, u_int,
struct cmd_list *);
%}
@ -101,8 +86,10 @@ static void cmd_parse_print_commands(struct cmd_parse_input *,
%union
{
char *token;
struct cmd_parse_arguments *arguments;
struct cmd_parse_argument *argument;
struct {
int argc;
char **argv;
} arguments;
int flag;
struct {
int flag;
@ -120,9 +107,8 @@ static void cmd_parse_print_commands(struct cmd_parse_input *,
%token ENDIF
%token <token> FORMAT TOKEN EQUALS
%type <token> expanded format
%type <token> argument expanded format
%type <arguments> arguments
%type <argument> argument
%type <flag> if_open if_elif
%type <elif> elif elif1
%type <commands> argument_statements statements statement
@ -223,16 +209,9 @@ assignment : EQUALS
{
struct cmd_parse_state *ps = &parse_state;
int flags = ps->input->flags;
int flag = 1;
struct cmd_parse_scope *scope;
if (ps->scope != NULL) {
flag = ps->scope->flag;
TAILQ_FOREACH(scope, &ps->stack, entry)
flag = flag && scope->flag;
}
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
if ((~flags & CMD_PARSE_PARSEONLY) &&
(ps->scope == NULL || ps->scope->flag))
environ_put(global_environ, $1, 0);
free($1);
}
@ -241,16 +220,9 @@ hidden_assignment : HIDDEN EQUALS
{
struct cmd_parse_state *ps = &parse_state;
int flags = ps->input->flags;
int flag = 1;
struct cmd_parse_scope *scope;
if (ps->scope != NULL) {
flag = ps->scope->flag;
TAILQ_FOREACH(scope, &ps->stack, entry)
flag = flag && scope->flag;
}
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
if ((~flags & CMD_PARSE_PARSEONLY) &&
(ps->scope == NULL || ps->scope->flag))
environ_put(global_environ, $2, ENVIRON_HIDDEN);
free($2);
}
@ -388,7 +360,7 @@ commands : command
struct cmd_parse_state *ps = &parse_state;
$$ = cmd_parse_new_commands();
if (!TAILQ_EMPTY(&$1->arguments) &&
if ($1->argc != 0 &&
(ps->scope == NULL || ps->scope->flag))
TAILQ_INSERT_TAIL($$, $1, entry);
else
@ -408,7 +380,7 @@ commands : command
{
struct cmd_parse_state *ps = &parse_state;
if (!TAILQ_EMPTY(&$3->arguments) &&
if ($3->argc != 0 &&
(ps->scope == NULL || ps->scope->flag)) {
$$ = $1;
TAILQ_INSERT_TAIL($$, $3, entry);
@ -429,38 +401,27 @@ command : assignment
$$ = xcalloc(1, sizeof *$$);
$$->line = ps->input->line;
TAILQ_INIT(&$$->arguments);
}
| optional_assignment TOKEN
{
struct cmd_parse_state *ps = &parse_state;
struct cmd_parse_argument *arg;
struct cmd_parse_state *ps = &parse_state;
$$ = xcalloc(1, sizeof *$$);
$$->line = ps->input->line;
TAILQ_INIT(&$$->arguments);
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_STRING;
arg->string = $2;
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
cmd_prepend_argv(&$$->argc, &$$->argv, $2);
}
| optional_assignment TOKEN arguments
{
struct cmd_parse_state *ps = &parse_state;
struct cmd_parse_argument *arg;
struct cmd_parse_state *ps = &parse_state;
$$ = xcalloc(1, sizeof *$$);
$$->line = ps->input->line;
TAILQ_INIT(&$$->arguments);
TAILQ_CONCAT(&$$->arguments, $3, entry);
free($3);
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_STRING;
arg->string = $2;
TAILQ_INSERT_HEAD(&$$->arguments, arg, entry);
$$->argc = $3.argc;
$$->argv = $3.argv;
cmd_prepend_argv(&$$->argc, &$$->argv, $2);
}
condition1 : if_open commands if_close
@ -544,34 +505,30 @@ elif1 : if_elif commands
arguments : argument
{
$$ = xcalloc(1, sizeof *$$);
TAILQ_INIT($$);
$$.argc = 1;
$$.argv = xreallocarray(NULL, 1, sizeof *$$.argv);
TAILQ_INSERT_HEAD($$, $1, entry);
$$.argv[0] = $1;
}
| argument arguments
{
TAILQ_INSERT_HEAD($2, $1, entry);
cmd_prepend_argv(&$2.argc, &$2.argv, $1);
free($1);
$$ = $2;
}
argument : TOKEN
{
$$ = xcalloc(1, sizeof *$$);
$$->type = CMD_PARSE_STRING;
$$->string = $1;
$$ = $1;
}
| EQUALS
{
$$ = xcalloc(1, sizeof *$$);
$$->type = CMD_PARSE_STRING;
$$->string = $1;
$$ = $1;
}
| '{' argument_statements
{
$$ = xcalloc(1, sizeof *$$);
$$->type = CMD_PARSE_COMMANDS;
$$->commands = $2;
$$ = cmd_parse_commands_to_string($2);
cmd_parse_free_commands($2);
}
argument_statements : statement '}'
@ -595,57 +552,30 @@ cmd_parse_get_error(const char *file, u_int line, const char *error)
if (file == NULL)
s = xstrdup(error);
else
xasprintf(&s, "%s:%u: %s", file, line, error);
xasprintf (&s, "%s:%u: %s", file, line, error);
return (s);
}
static void
cmd_parse_print_commands(struct cmd_parse_input *pi, struct cmd_list *cmdlist)
cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line,
struct cmd_list *cmdlist)
{
char *s;
if (pi->item == NULL || (~pi->flags & CMD_PARSE_VERBOSE))
return;
s = cmd_list_print(cmdlist, 0);
if (pi->file != NULL)
cmdq_print(pi->item, "%s:%u: %s", pi->file, pi->line, s);
else
cmdq_print(pi->item, "%u: %s", pi->line, s);
free(s);
}
static void
cmd_parse_free_argument(struct cmd_parse_argument *arg)
{
switch (arg->type) {
case CMD_PARSE_STRING:
free(arg->string);
break;
case CMD_PARSE_COMMANDS:
cmd_parse_free_commands(arg->commands);
break;
case CMD_PARSE_PARSED_COMMANDS:
cmd_list_free(arg->cmdlist);
break;
}
free(arg);
}
static void
cmd_parse_free_arguments(struct cmd_parse_arguments *args)
{
struct cmd_parse_argument *arg, *arg1;
TAILQ_FOREACH_SAFE(arg, args, entry, arg1) {
TAILQ_REMOVE(args, arg, entry);
cmd_parse_free_argument(arg);
if (pi->item != NULL && (pi->flags & CMD_PARSE_VERBOSE)) {
s = cmd_list_print(cmdlist, 0);
if (pi->file != NULL)
cmdq_print(pi->item, "%s:%u: %s", pi->file, line, s);
else
cmdq_print(pi->item, "%u: %s", line, s);
free(s);
}
}
static void
cmd_parse_free_command(struct cmd_parse_command *cmd)
{
cmd_parse_free_arguments(&cmd->arguments);
cmd_free_argv(cmd->argc, cmd->argv);
free(cmd);
}
@ -655,7 +585,7 @@ cmd_parse_new_commands(void)
struct cmd_parse_commands *cmds;
cmds = xmalloc(sizeof *cmds);
TAILQ_INIT(cmds);
TAILQ_INIT (cmds);
return (cmds);
}
@ -671,6 +601,30 @@ cmd_parse_free_commands(struct cmd_parse_commands *cmds)
free(cmds);
}
static char *
cmd_parse_commands_to_string(struct cmd_parse_commands *cmds)
{
struct cmd_parse_command *cmd;
char *string = NULL, *s, *line;
TAILQ_FOREACH(cmd, cmds, entry) {
line = cmd_stringify_argv(cmd->argc, cmd->argv);
if (string == NULL)
s = line;
else {
xasprintf(&s, "%s ; %s", s, line);
free(line);
}
free(string);
string = s;
}
if (string == NULL)
string = xstrdup("");
log_debug("%s: %s", __func__, string);
return (string);
}
static struct cmd_parse_commands *
cmd_parse_run_parser(char **cause)
{
@ -720,170 +674,72 @@ cmd_parse_do_buffer(const char *buf, size_t len, struct cmd_parse_input *pi,
return (cmd_parse_run_parser(cause));
}
static void
cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix)
{
struct cmd_parse_command *cmd;
struct cmd_parse_argument *arg;
u_int i, j;
char *s;
i = 0;
TAILQ_FOREACH(cmd, cmds, entry) {
j = 0;
TAILQ_FOREACH(arg, &cmd->arguments, entry) {
switch (arg->type) {
case CMD_PARSE_STRING:
log_debug("%s %u:%u: %s", prefix, i, j,
arg->string);
break;
case CMD_PARSE_COMMANDS:
xasprintf(&s, "%s %u:%u", prefix, i, j);
cmd_parse_log_commands(arg->commands, s);
free(s);
break;
case CMD_PARSE_PARSED_COMMANDS:
s = cmd_list_print(arg->cmdlist, 0);
log_debug("%s %u:%u: %s", prefix, i, j, s);
free(s);
break;
}
j++;
}
i++;
}
}
static int
cmd_parse_expand_alias(struct cmd_parse_command *cmd,
struct cmd_parse_input *pi, struct cmd_parse_result *pr)
{
struct cmd_parse_argument *arg, *arg1, *first;
struct cmd_parse_commands *cmds;
struct cmd_parse_command *last;
char *alias, *name, *cause;
if (pi->flags & CMD_PARSE_NOALIAS)
return (0);
memset(pr, 0, sizeof *pr);
first = TAILQ_FIRST(&cmd->arguments);
if (first == NULL || first->type != CMD_PARSE_STRING) {
pr->status = CMD_PARSE_SUCCESS;
pr->cmdlist = cmd_list_new();
return (1);
}
name = first->string;
alias = cmd_get_alias(name);
if (alias == NULL)
return (0);
log_debug("%s: %u alias %s = %s", __func__, pi->line, name, alias);
cmds = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause);
free(alias);
if (cmds == NULL) {
pr->status = CMD_PARSE_ERROR;
pr->error = cause;
return (1);
}
last = TAILQ_LAST(cmds, cmd_parse_commands);
if (last == NULL) {
pr->status = CMD_PARSE_SUCCESS;
pr->cmdlist = cmd_list_new();
return (1);
}
TAILQ_REMOVE(&cmd->arguments, first, entry);
cmd_parse_free_argument(first);
TAILQ_FOREACH_SAFE(arg, &cmd->arguments, entry, arg1) {
TAILQ_REMOVE(&cmd->arguments, arg, entry);
TAILQ_INSERT_TAIL(&last->arguments, arg, entry);
}
cmd_parse_log_commands(cmds, __func__);
pi->flags |= CMD_PARSE_NOALIAS;
cmd_parse_build_commands(cmds, pi, pr);
pi->flags &= ~CMD_PARSE_NOALIAS;
return (1);
}
static void
cmd_parse_build_command(struct cmd_parse_command *cmd,
struct cmd_parse_input *pi, struct cmd_parse_result *pr)
{
struct cmd_parse_argument *arg;
struct cmd *add;
char *cause;
struct args_value *values = NULL;
u_int count = 0, idx;
memset(pr, 0, sizeof *pr);
if (cmd_parse_expand_alias(cmd, pi, pr))
return;
TAILQ_FOREACH(arg, &cmd->arguments, entry) {
values = xrecallocarray(values, count, count + 1,
sizeof *values);
switch (arg->type) {
case CMD_PARSE_STRING:
values[count].type = ARGS_STRING;
values[count].string = xstrdup(arg->string);
break;
case CMD_PARSE_COMMANDS:
cmd_parse_build_commands(arg->commands, pi, pr);
if (pr->status != CMD_PARSE_SUCCESS)
goto out;
values[count].type = ARGS_COMMANDS;
values[count].cmdlist = pr->cmdlist;
break;
case CMD_PARSE_PARSED_COMMANDS:
values[count].type = ARGS_COMMANDS;
values[count].cmdlist = arg->cmdlist;
values[count].cmdlist->references++;
break;
}
count++;
}
add = cmd_parse(values, count, pi->file, pi->line, &cause);
if (add == NULL) {
pr->status = CMD_PARSE_ERROR;
pr->error = cmd_parse_get_error(pi->file, pi->line, cause);
free(cause);
goto out;
}
pr->status = CMD_PARSE_SUCCESS;
pr->cmdlist = cmd_list_new();
cmd_list_append(pr->cmdlist, add);
out:
for (idx = 0; idx < count; idx++)
args_free_value(&values[idx]);
free(values);
}
static void
static struct cmd_parse_result *
cmd_parse_build_commands(struct cmd_parse_commands *cmds,
struct cmd_parse_input *pi, struct cmd_parse_result *pr)
struct cmd_parse_input *pi)
{
struct cmd_parse_command *cmd;
static struct cmd_parse_result pr;
struct cmd_parse_commands *cmds2;
struct cmd_parse_command *cmd, *cmd2, *next, *next2, *after;
u_int line = UINT_MAX;
struct cmd_list *current = NULL, *result;
char *s;
memset(pr, 0, sizeof *pr);
int i;
struct cmd_list *cmdlist = NULL, *result;
struct cmd *add;
char *name, *alias, *cause, *s;
/* Check for an empty list. */
if (TAILQ_EMPTY(cmds)) {
pr->status = CMD_PARSE_SUCCESS;
pr->cmdlist = cmd_list_new();
return;
cmd_parse_free_commands(cmds);
pr.status = CMD_PARSE_EMPTY;
return (&pr);
}
/*
* Walk the commands and expand any aliases. Each alias is parsed
* individually to a new command list, any trailing arguments appended
* to the last command, and all commands inserted into the original
* command list.
*/
TAILQ_FOREACH_SAFE(cmd, cmds, entry, next) {
name = cmd->argv[0];
alias = cmd_get_alias(name);
if (alias == NULL)
continue;
line = cmd->line;
log_debug("%s: %u %s = %s", __func__, line, name, alias);
pi->line = line;
cmds2 = cmd_parse_do_buffer(alias, strlen(alias), pi, &cause);
free(alias);
if (cmds2 == NULL) {
pr.status = CMD_PARSE_ERROR;
pr.error = cause;
goto out;
}
cmd2 = TAILQ_LAST(cmds2, cmd_parse_commands);
if (cmd2 == NULL) {
TAILQ_REMOVE(cmds, cmd, entry);
cmd_parse_free_command(cmd);
continue;
}
for (i = 1; i < cmd->argc; i++)
cmd_append_argv(&cmd2->argc, &cmd2->argv, cmd->argv[i]);
after = cmd;
TAILQ_FOREACH_SAFE(cmd2, cmds2, entry, next2) {
cmd2->line = line;
TAILQ_REMOVE(cmds2, cmd2, entry);
TAILQ_INSERT_AFTER(cmds, after, cmd2, entry);
after = cmd2;
}
cmd_parse_free_commands(cmds2);
TAILQ_REMOVE(cmds, cmd, entry);
cmd_parse_free_command(cmd);
}
cmd_parse_log_commands(cmds, __func__);
/*
* Parse each command into a command list. Create a new command list
@ -893,39 +749,49 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds,
*/
result = cmd_list_new();
TAILQ_FOREACH(cmd, cmds, entry) {
if (((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) {
if (current != NULL) {
cmd_parse_print_commands(pi, current);
cmd_list_move(result, current);
cmd_list_free(current);
}
current = cmd_list_new();
}
if (current == NULL)
current = cmd_list_new();
line = pi->line = cmd->line;
name = cmd->argv[0];
log_debug("%s: %u %s", __func__, cmd->line, name);
cmd_log_argv(cmd->argc, cmd->argv, __func__);
cmd_parse_build_command(cmd, pi, pr);
if (pr->status != CMD_PARSE_SUCCESS) {
cmd_list_free(result);
cmd_list_free(current);
return;
if (cmdlist == NULL ||
((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) {
if (cmdlist != NULL) {
cmd_parse_print_commands(pi, line, cmdlist);
cmd_list_move(result, cmdlist);
cmd_list_free(cmdlist);
}
cmdlist = cmd_list_new();
}
cmd_list_append_all(current, pr->cmdlist);
cmd_list_free(pr->cmdlist);
line = cmd->line;
add = cmd_parse(cmd->argc, cmd->argv, pi->file, line, &cause);
if (add == NULL) {
cmd_list_free(result);
pr.status = CMD_PARSE_ERROR;
pr.error = cmd_parse_get_error(pi->file, line, cause);
free(cause);
cmd_list_free(cmdlist);
goto out;
}
cmd_list_append(cmdlist, add);
}
if (current != NULL) {
cmd_parse_print_commands(pi, current);
cmd_list_move(result, current);
cmd_list_free(current);
if (cmdlist != NULL) {
cmd_parse_print_commands(pi, line, cmdlist);
cmd_list_move(result, cmdlist);
cmd_list_free(cmdlist);
}
s = cmd_list_print(result, 0);
log_debug("%s: %s", __func__, s);
free(s);
pr->status = CMD_PARSE_SUCCESS;
pr->cmdlist = result;
pr.status = CMD_PARSE_SUCCESS;
pr.cmdlist = result;
out:
cmd_parse_free_commands(cmds);
return (&pr);
}
struct cmd_parse_result *
@ -948,10 +814,7 @@ cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi)
pr.error = cause;
return (&pr);
}
cmd_parse_build_commands(cmds, pi, &pr);
cmd_parse_free_commands(cmds);
return (&pr);
return (cmd_parse_build_commands(cmds, pi));
}
struct cmd_parse_result *
@ -982,6 +845,8 @@ cmd_parse_and_insert(const char *s, struct cmd_parse_input *pi,
pr = cmd_parse_from_string(s, pi);
switch (pr->status) {
case CMD_PARSE_EMPTY:
break;
case CMD_PARSE_ERROR:
if (error != NULL)
*error = pr->error;
@ -1006,6 +871,8 @@ cmd_parse_and_append(const char *s, struct cmd_parse_input *pi,
pr = cmd_parse_from_string(s, pi);
switch (pr->status) {
case CMD_PARSE_EMPTY:
break;
case CMD_PARSE_ERROR:
if (error != NULL)
*error = pr->error;
@ -1036,8 +903,9 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi)
memset(&pr, 0, sizeof pr);
if (len == 0) {
pr.status = CMD_PARSE_SUCCESS;
pr.cmdlist = cmd_list_new();
pr.status = CMD_PARSE_EMPTY;
pr.cmdlist = NULL;
pr.error = NULL;
return (&pr);
}
@ -1047,24 +915,18 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi)
pr.error = cause;
return (&pr);
}
cmd_parse_build_commands(cmds, pi, &pr);
cmd_parse_free_commands(cmds);
return (&pr);
return (cmd_parse_build_commands(cmds, pi));
}
struct cmd_parse_result *
cmd_parse_from_arguments(struct args_value *values, u_int count,
struct cmd_parse_input *pi)
cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
{
static struct cmd_parse_result pr;
struct cmd_parse_input input;
struct cmd_parse_commands *cmds;
struct cmd_parse_command *cmd;
struct cmd_parse_argument *arg;
u_int i;
char *copy;
size_t size;
int end;
struct cmd_parse_input input;
struct cmd_parse_commands *cmds;
struct cmd_parse_command *cmd;
char **copy, **new_argv;
size_t size;
int i, last, new_argc;
/*
* The commands are already split up into arguments, so just separate
@ -1075,56 +937,62 @@ cmd_parse_from_arguments(struct args_value *values, u_int count,
memset(&input, 0, sizeof input);
pi = &input;
}
memset(&pr, 0, sizeof pr);
cmd_log_argv(argc, argv, "%s", __func__);
cmds = cmd_parse_new_commands();
copy = cmd_copy_argv(argc, argv);
cmd = xcalloc(1, sizeof *cmd);
cmd->line = pi->line;
TAILQ_INIT(&cmd->arguments);
last = 0;
for (i = 0; i < argc; i++) {
size = strlen(copy[i]);
if (size == 0 || copy[i][size - 1] != ';')
continue;
copy[i][--size] = '\0';
if (size > 0 && copy[i][size - 1] == '\\') {
copy[i][size - 1] = ';';
continue;
}
new_argc = i - last;
new_argv = copy + last;
if (size != 0)
new_argc++;
if (new_argc != 0) {
cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__,
i);
for (i = 0; i < count; i++) {
end = 0;
if (values[i].type == ARGS_STRING) {
copy = xstrdup(values[i].string);
size = strlen(copy);
if (size != 0 && copy[size - 1] == ';') {
copy[--size] = '\0';
if (size > 0 && copy[size - 1] == '\\')
copy[size - 1] = ';';
else
end = 1;
}
if (!end || size != 0) {
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_STRING;
arg->string = copy;
TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
} else
free(copy);
} else if (values[i].type == ARGS_COMMANDS) {
arg = xcalloc(1, sizeof *arg);
arg->type = CMD_PARSE_PARSED_COMMANDS;
arg->cmdlist = values[i].cmdlist;
arg->cmdlist->references++;
TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
} else
fatalx("unknown argument type");
if (end) {
TAILQ_INSERT_TAIL(cmds, cmd, entry);
cmd = xcalloc(1, sizeof *cmd);
cmd->line = pi->line;
TAILQ_INIT(&cmd->arguments);
cmd->argc = new_argc;
cmd->argv = cmd_copy_argv(new_argc, new_argv);
TAILQ_INSERT_TAIL(cmds, cmd, entry);
}
last = i + 1;
}
if (last != argc) {
new_argv = copy + last;
new_argc = argc - last;
if (new_argc != 0) {
cmd_log_argv(new_argc, new_argv, "%s: at %u", __func__,
last);
cmd = xcalloc(1, sizeof *cmd);
cmd->line = pi->line;
cmd->argc = new_argc;
cmd->argv = cmd_copy_argv(new_argc, new_argv);
TAILQ_INSERT_TAIL(cmds, cmd, entry);
}
}
if (!TAILQ_EMPTY(&cmd->arguments))
TAILQ_INSERT_TAIL(cmds, cmd, entry);
else
free(cmd);
cmd_parse_build_commands(cmds, pi, &pr);
cmd_parse_free_commands(cmds);
return (&pr);
cmd_free_argv(argc, copy);
return (cmd_parse_build_commands(cmds, pi));
}
static int printflike(1, 2)
@ -1287,16 +1155,6 @@ yylex(void)
continue;
}
if (ch == '\r') {
/*
* Treat \r\n as \n.
*/
ch = yylex_getc();
if (ch != '\n') {
yylex_ungetc(ch);
ch = '\r';
}
}
if (ch == '\n') {
/*
* End of line. Update the line number.
@ -1451,7 +1309,7 @@ yylex_token_escape(char **buf, size_t *len)
if (o3 >= '0' && o3 <= '7') {
ch = 64 * (ch - '0') +
8 * (o2 - '0') +
(o3 - '0');
(o3 - '0');
yylex_append1(buf, len, ch);
return (1);
}
@ -1627,7 +1485,6 @@ yylex_token_tilde(char **buf, size_t *len)
static char *
yylex_token(int ch)
{
struct cmd_parse_state *ps = &parse_state;
char *buf;
size_t len;
enum { START,
@ -1640,34 +1497,13 @@ yylex_token(int ch)
for (;;) {
/* EOF or \n are always the end of the token. */
if (ch == EOF) {
log_debug("%s: end at EOF", __func__);
if (ch == EOF || (state == NONE && ch == '\n'))
break;
}
if (state == NONE && ch == '\r') {
ch = yylex_getc();
if (ch != '\n') {
yylex_ungetc(ch);
ch = '\r';
}
}
if (ch == '\n') {
if (state == NONE) {
log_debug("%s: end at EOL", __func__);
break;
}
ps->input->line++;
}
/* Whitespace or ; or } ends a token unless inside quotes. */
if (state == NONE && (ch == ' ' || ch == '\t')) {
log_debug("%s: end at WS", __func__);
if ((ch == ' ' || ch == '\t' || ch == ';' || ch == '}') &&
state == NONE)
break;
}
if (state == NONE && (ch == ';' || ch == '}')) {
log_debug("%s: end at %c", __func__, ch);
break;
}
/*
* Spaces and comments inside quotes after \n are removed but

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_paste_buffer_entry = {
.name = "paste-buffer",
.alias = "pasteb",
.args = { "db:prs:t:", 0, 0, NULL },
.args = { "db:prs:t:", 0, 0 },
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
CMD_TARGET_PANE_USAGE,
@ -54,11 +54,6 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
size_t seplen, bufsize;
int bracket = args_has(args, 'p');
if (window_pane_exited(wp)) {
cmdq_error(item, "target pane has exited");
return (CMD_RETURN_ERROR);
}
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');

View File

@ -43,8 +43,8 @@ const struct cmd_entry cmd_pipe_pane_entry = {
.name = "pipe-pane",
.alias = "pipep",
.args = { "IOot:", 0, 1, NULL },
.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [shell-command]",
.args = { "IOot:", 0, 1 },
.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [command]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -67,12 +67,6 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
struct format_tree *ft;
sigset_t set, oldset;
/* Do nothing if pane is dead. */
if (window_pane_exited(wp)) {
cmdq_error(item, "target pane has exited");
return (CMD_RETURN_ERROR);
}
/* Destroy the old pipe. */
old_fd = wp->pipe_fd;
if (wp->pipe_fd != -1) {
@ -87,7 +81,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
}
/* If no pipe command, that is enough. */
if (args_count(args) == 0 || *args_string(args, 0) == '\0')
if (args->argc == 0 || *args->argv[0] == '\0')
return (CMD_RETURN_NORMAL);
/*
@ -117,7 +111,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
/* Expand the command. */
ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0);
format_defaults(ft, tc, s, wl, wp);
cmd = format_expand_time(ft, args_string(args, 0));
cmd = format_expand_time(ft, args->argv[0]);
format_free(ft);
/* Fork the child. */
@ -136,7 +130,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
sigprocmask(SIG_SETMASK, &oldset, NULL);
close(pipe_fd[0]);
null_fd = open(_PATH_DEVNULL, O_WRONLY);
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0);
if (out) {
if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
_exit(1);

View File

@ -19,11 +19,9 @@
#include <sys/types.h>
#include <ctype.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
@ -126,7 +124,7 @@ cmdq_new(void)
{
struct cmdq_list *queue;
queue = xcalloc(1, sizeof *queue);
queue = xcalloc (1, sizeof *queue);
TAILQ_INIT (&queue->list);
return (queue);
}
@ -236,10 +234,8 @@ cmdq_link_state(struct cmdq_state *state)
/* Make a copy of a state. */
struct cmdq_state *
cmdq_copy_state(struct cmdq_state *state, struct cmd_find_state *current)
cmdq_copy_state(struct cmdq_state *state)
{
if (current != NULL)
return (cmdq_new_state(current, &state->event, state->flags));
return (cmdq_new_state(&state->current, &state->event, state->flags));
}
@ -273,15 +269,6 @@ cmdq_add_format(struct cmdq_state *state, const char *key, const char *fmt, ...)
free(value);
}
/* Add formats to command queue. */
void
cmdq_add_formats(struct cmdq_state *state, struct format_tree *ft)
{
if (state->formats == NULL)
state->formats = format_create(NULL, NULL, FORMAT_NONE, 0);
format_merge(state->formats, ft);
}
/* Merge formats from item. */
void
cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft)
@ -356,12 +343,12 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item,
struct cmdq_state *state = item->state;
struct cmd *cmd = item->cmd;
struct args *args = cmd_get_args(cmd);
struct args_entry *ae;
struct args_value *av;
struct args_entry *entryp;
struct args_value *valuep;
struct options *oo;
va_list ap;
char *name, tmp[32], flag, *arguments;
u_int i;
int i;
const char *value;
struct cmdq_item *new_item;
struct cmdq_state *new_state;
@ -398,11 +385,11 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item,
cmdq_add_format(new_state, "hook_arguments", "%s", arguments);
free(arguments);
for (i = 0; i < args_count(args); i++) {
for (i = 0; i < args->argc; i++) {
xsnprintf(tmp, sizeof tmp, "hook_argument_%d", i);
cmdq_add_format(new_state, tmp, "%s", args_string(args, i));
cmdq_add_format(new_state, tmp, "%s", args->argv[i]);
}
flag = args_first(args, &ae);
flag = args_first(args, &entryp);
while (flag != 0) {
value = args_get(args, flag);
if (value == NULL) {
@ -414,15 +401,15 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item,
}
i = 0;
av = args_first_value(args, flag);
while (av != NULL) {
value = args_first_value(args, flag, &valuep);
while (value != NULL) {
xsnprintf(tmp, sizeof tmp, "hook_flag_%c_%d", flag, i);
cmdq_add_format(new_state, tmp, "%s", av->string);
cmdq_add_format(new_state, tmp, "%s", value);
i++;
av = args_next_value(av);
value = args_next_value(&valuep);
}
flag = args_next(&ae);
flag = args_next(&entryp);
}
a = options_array_first(o);
@ -482,13 +469,6 @@ cmdq_remove_group(struct cmdq_item *item)
}
}
/* Empty command callback. */
static enum cmd_retval
cmdq_empty_command(__unused struct cmdq_item *item, __unused void *data)
{
return (CMD_RETURN_NORMAL);
}
/* Get a command for the command queue. */
struct cmdq_item *
cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state)
@ -498,14 +478,12 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state)
const struct cmd_entry *entry;
int created = 0;
if ((cmd = cmd_list_first(cmdlist)) == NULL)
return (cmdq_get_callback(cmdq_empty_command, NULL));
if (state == NULL) {
state = cmdq_new_state(NULL, NULL, 0);
created = 1;
}
cmd = cmd_list_first(cmdlist);
while (cmd != NULL) {
entry = cmd_get_entry(cmd);
@ -562,31 +540,17 @@ cmdq_add_message(struct cmdq_item *item)
{
struct client *c = item->client;
struct cmdq_state *state = item->state;
const char *key;
const char *name, *key;
char *tmp;
uid_t uid;
struct passwd *pw;
char *user = NULL;
tmp = cmd_print(item->cmd);
if (c != NULL) {
uid = proc_get_peer_uid(c->peer);
if (uid != (uid_t)-1 && uid != getuid()) {
if ((pw = getpwuid(uid)) != NULL)
xasprintf(&user, "[%s]", pw->pw_name);
else
user = xstrdup("[unknown]");
} else
user = xstrdup("");
name = c->name;
if (c->session != NULL && state->event.key != KEYC_NONE) {
key = key_string_lookup_key(state->event.key, 0);
server_add_message("%s%s key %s: %s", c->name, user,
key, tmp);
} else {
server_add_message("%s%s command: %s", c->name, user,
tmp);
}
free(user);
server_add_message("%s key %s: %s", name, key, tmp);
} else
server_add_message("%s command: %s", name, tmp);
} else
server_add_message("command: %s", tmp);
free(tmp);
@ -664,18 +628,9 @@ cmdq_fire_command(struct cmdq_item *item)
out:
item->client = saved;
if (retval == CMD_RETURN_ERROR) {
fsp = NULL;
if (cmd_find_valid_state(&item->target))
fsp = &item->target;
else if (cmd_find_valid_state(&item->state->current))
fsp = &item->state->current;
else if (cmd_find_from_client(&fs, item->client, 0) == 0)
fsp = &fs;
cmdq_insert_hook(fsp != NULL ? fsp->s : NULL, item, fsp,
"command-error");
if (retval == CMD_RETURN_ERROR)
cmdq_guard(item, "error", flags);
} else
else
cmdq_guard(item, "end", flags);
return (retval);
}
@ -814,10 +769,10 @@ cmdq_running(struct client *c)
struct cmdq_list *queue = cmdq_get(c);
if (queue->item == NULL)
return (NULL);
if (queue->item->flags & CMDQ_WAITING)
return (NULL);
return (queue->item);
return (NULL);
if (queue->item->flags & CMDQ_WAITING)
return (NULL);
return (queue->item);
}
/* Print a guard line. */
@ -832,30 +787,45 @@ cmdq_guard(struct cmdq_item *item, const char *guard, int flags)
control_write(c, "%%%s %ld %u %d", guard, t, number, flags);
}
/* Show message from command. */
void
cmdq_print_data(struct cmdq_item *item, struct evbuffer *evb)
{
server_client_print(item->client, 1, evb);
}
/* Show message from command. */
void
cmdq_print(struct cmdq_item *item, const char *fmt, ...)
{
va_list ap;
struct evbuffer *evb;
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
struct client *c = item->client;
struct window_pane *wp;
struct window_mode_entry *wme;
va_list ap;
char *tmp, *msg;
va_start(ap, fmt);
evbuffer_add_vprintf(evb, fmt, ap);
xvasprintf(&msg, fmt, ap);
va_end(ap);
cmdq_print_data(item, evb);
evbuffer_free(evb);
log_debug("%s: %s", __func__, msg);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
if (~c->flags & CLIENT_UTF8) {
tmp = msg;
msg = utf8_sanitize(tmp);
free(tmp);
}
if (c->flags & CLIENT_CONTROL)
control_write(c, "%s", msg);
else
file_print(c, "%s\n", msg);
} else {
wp = server_client_get_pane(c);
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode != &window_view_mode) {
window_pane_set_mode(wp, NULL, &window_view_mode, NULL,
NULL);
}
window_copy_add(wp, "%s", msg);
}
free(msg);
}
/* Show error from command. */
@ -892,7 +862,7 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...)
c->retval = 1;
} else {
*msg = toupper((u_char) *msg);
status_message_set(c, -1, 1, 0, 0, "%s", msg);
status_message_set(c, -1, 1, 0, "%s", msg);
}
free(msg);

View File

@ -34,10 +34,9 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
.args = { "A:B:cC:Df:r:F:l::LRSt:U", 0, 1, NULL },
.args = { "A:B:cC:Df:F:lLRSt:U", 0, 1 },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE
" [adjustment]",
"[-C XxY] [-f flags] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,
.exec = cmd_refresh_client_exec
@ -78,58 +77,6 @@ out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_control_client_size(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
const char *size = args_get(args, 'C');
u_int w, x, y;
struct client_window *cw;
if (sscanf(size, "@%u:%ux%u", &w, &x, &y) == 3) {
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
cmdq_error(item, "size too small or too big");
return (CMD_RETURN_ERROR);
}
log_debug("%s: client %s window @%u: size %ux%u", __func__,
tc->name, w, x, y);
cw = server_client_add_client_window(tc, w);
cw->sx = x;
cw->sy = y;
tc->flags |= CLIENT_WINDOWSIZECHANGED;
recalculate_sizes_now(1);
return (CMD_RETURN_NORMAL);
}
if (sscanf(size, "@%u:", &w) == 1) {
cw = server_client_get_client_window(tc, w);
if (cw != NULL) {
log_debug("%s: client %s window @%u: no size", __func__,
tc->name, w);
cw->sx = 0;
cw->sy = 0;
recalculate_sizes_now(1);
}
return (CMD_RETURN_NORMAL);
}
if (sscanf(size, "%u,%u", &x, &y) != 2 &&
sscanf(size, "%ux%u", &x, &y) != 2) {
cmdq_error(item, "bad size argument");
return (CMD_RETURN_ERROR);
}
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
cmdq_error(item, "size too small or too big");
return (CMD_RETURN_ERROR);
}
tty_set_size(&tc->tty, x, y, 0, 0);
tc->flags |= CLIENT_SIZECHANGED;
recalculate_sizes_now(1);
return (CMD_RETURN_NORMAL);
}
static void
cmd_refresh_client_update_offset(struct client *tc, const char *value)
{
@ -163,65 +110,6 @@ out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *tc = cmdq_get_target_client(item);
const char *p;
u_int i;
struct cmd_find_state fs;
p = args_get(args, 'l');
if (p == NULL) {
if (tc->flags & CLIENT_CLIPBOARDBUFFER)
return (CMD_RETURN_NORMAL);
tc->flags |= CLIENT_CLIPBOARDBUFFER;
} else {
if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0)
return (CMD_RETURN_ERROR);
for (i = 0; i < tc->clipboard_npanes; i++) {
if (tc->clipboard_panes[i] == fs.wp->id)
break;
}
if (i != tc->clipboard_npanes)
return (CMD_RETURN_NORMAL);
tc->clipboard_panes = xreallocarray(tc->clipboard_panes,
tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes);
tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id;
}
tty_clipboard_query(&tc->tty);
return (CMD_RETURN_NORMAL);
}
static void
cmd_refresh_report(struct tty *tty, const char *value)
{
struct window_pane *wp;
u_int pane;
size_t size = 0;
char *copy, *split;
if (*value != '%')
return;
copy = xstrdup(value);
if ((split = strchr(copy, ':')) == NULL)
goto out;
*split++ = '\0';
if (sscanf(copy, "%%%u", &pane) != 1)
goto out;
wp = window_pane_find_by_id(pane);
if (wp == NULL)
goto out;
tty_keys_colours(tty, split, strlen(split), &size, &wp->control_fg,
&wp->control_bg);
out:
free(copy);
}
static enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
{
@ -229,8 +117,8 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
struct client *tc = cmdq_get_target_client(item);
struct tty *tty = &tc->tty;
struct window *w;
const char *errstr;
u_int adjust;
const char *size, *errstr, *value;
u_int x, y, adjust;
struct args_value *av;
if (args_has(args, 'c') ||
@ -239,11 +127,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
args_has(args, 'U') ||
args_has(args, 'D'))
{
if (args_count(args) == 0)
if (args->argc == 0)
adjust = 1;
else {
adjust = strtonum(args_string(args, 0), 1, INT_MAX,
&errstr);
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
@ -284,40 +171,54 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'l'))
return (cmd_refresh_client_clipboard(self, item));
if (args_has(args, 'l')) {
tty_putcode_ptr2(&tc->tty, TTYC_MS, "", "?");
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'F')) /* -F is an alias for -f */
server_client_set_flags(tc, args_get(args, 'F'));
if (args_has(args, 'f'))
server_client_set_flags(tc, args_get(args, 'f'));
if (args_has(args, 'r'))
cmd_refresh_report(tty, args_get(args, 'r'));
if (args_has(args, 'A')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
av = args_first_value(args, 'A');
while (av != NULL) {
cmd_refresh_client_update_offset(tc, av->string);
av = args_next_value(av);
value = args_first_value(args, 'A', &av);
while (value != NULL) {
cmd_refresh_client_update_offset(tc, value);
value = args_next_value(&av);
}
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'B')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
av = args_first_value(args, 'B');
while (av != NULL) {
cmd_refresh_client_update_subscription(tc, av->string);
av = args_next_value(av);
value = args_first_value(args, 'B', &av);
while (value != NULL) {
cmd_refresh_client_update_subscription(tc, value);
value = args_next_value(&av);
}
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'C')) {
if (~tc->flags & CLIENT_CONTROL)
goto not_control_client;
return (cmd_refresh_client_control_client_size(self, item));
size = args_get(args, 'C');
if (sscanf(size, "%u,%u", &x, &y) != 2 &&
sscanf(size, "%ux%u", &x, &y) != 2) {
cmdq_error(item, "bad size argument");
return (CMD_RETURN_ERROR);
}
if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
cmdq_error(item, "size too small or too big");
return (CMD_RETURN_ERROR);
}
tty_set_size(&tc->tty, x, y, 0, 0);
tc->flags |= CLIENT_SIZECHANGED;
recalculate_sizes_now(1);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'S')) {

View File

@ -34,7 +34,7 @@ const struct cmd_entry cmd_rename_session_entry = {
.name = "rename-session",
.alias = "rename",
.args = { "t:", 1, 1, NULL },
.args = { "t:", 1, 1 },
.usage = CMD_TARGET_SESSION_USAGE " new-name",
.target = { 't', CMD_FIND_SESSION, 0 },
@ -51,13 +51,8 @@ cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = target->s;
char *newname, *tmp;
tmp = format_single_from_target(item, args_string(args, 0));
tmp = format_single_from_target(item, args->argv[0]);
newname = session_check_name(tmp);
if (newname == NULL) {
cmdq_error(item, "invalid session: %s", tmp);
free(tmp);
return (CMD_RETURN_ERROR);
}
free(tmp);
if (strcmp(newname, s->name) == 0) {
free(newname);

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_rename_window_entry = {
.name = "rename-window",
.alias = "renamew",
.args = { "t:", 1, 1, NULL },
.args = { "t:", 1, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " new-name",
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -50,7 +50,7 @@ cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item)
struct winlink *wl = target->wl;
char *newname;
newname = format_single_from_target(item, args_string(args, 0));
newname = format_single_from_target(item, args->argv[0]);
window_set_name(wl->window, newname);
options_set_number(wl->window->options, "automatic-rename", 0);

View File

@ -36,7 +36,7 @@ const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane",
.alias = "resizep",
.args = { "DLMRTt:Ux:y:Z", 0, 1, NULL },
.args = { "DLMRTt:Ux:y:Z", 0, 1 },
.usage = "[-DLMRTUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
"[adjustment]",
@ -60,7 +60,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
const char *errstr;
char *cause;
u_int adjust;
int x, y, status;
int x, y;
struct grid *gd = wp->base.grid;
if (args_has(args, 'T')) {
@ -87,7 +87,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED)
window_unzoom(w, 1);
window_unzoom(w);
else
window_zoom(wp);
server_redraw_window(w);
@ -95,10 +95,10 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
}
server_unzoom_window(w);
if (args_count(args) == 0)
if (args->argc == 0)
adjust = 1;
else {
adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
@ -121,17 +121,6 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
status = options_get_number(w->options, "pane-border-status");
switch (status) {
case PANE_STATUS_TOP:
if (y != INT_MAX && wp->yoff == 1)
y++;
break;
case PANE_STATUS_BOTTOM:
if (y != INT_MAX && wp->yoff + wp->sy == w->sy - 1)
y++;
break;
}
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
}

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_resize_window_entry = {
.name = "resize-window",
.alias = "resizew",
.args = { "aADLRt:Ux:y:", 0, 1, NULL },
.args = { "aADLRt:Ux:y:", 0, 1 },
.usage = "[-aADLRU] [-x width] [-y height] " CMD_TARGET_WINDOW_USAGE " "
"[adjustment]",
@ -53,12 +53,13 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = target->s;
const char *errstr;
char *cause;
u_int adjust, sx, sy, xpixel = 0, ypixel = 0;
u_int adjust, sx, sy;
int xpixel = -1, ypixel = -1;
if (args_count(args) == 0)
if (args->argc == 0)
adjust = 1;
else {
adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "adjustment %s", errstr);
return (CMD_RETURN_ERROR);
@ -107,9 +108,7 @@ cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
}
options_set_number(w->options, "window-size", WINDOW_SIZE_MANUAL);
w->manual_sx = sx;
w->manual_sy = sy;
recalculate_size(w, 1);
resize_window(w, sx, sy, xpixel, ypixel);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,9 +34,9 @@ const struct cmd_entry cmd_respawn_pane_entry = {
.name = "respawn-pane",
.alias = "respawnp",
.args = { "c:e:kt:", 0, -1, NULL },
.args = { "c:e:kt:", 0, -1 },
.usage = "[-k] [-c start-directory] [-e environment] "
CMD_TARGET_PANE_USAGE " [shell-command [argument ...]]",
CMD_TARGET_PANE_USAGE " [command]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -49,26 +49,31 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct spawn_context sc = { 0 };
struct spawn_context sc;
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
char *cause = NULL;
struct args_value *av;
const char *add;
struct args_value *value;
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.wl = wl;
sc.wp0 = wp;
sc.lc = NULL;
args_to_vector(args, &sc.argc, &sc.argv);
sc.name = NULL;
sc.argc = args->argc;
sc.argv = args->argv;
sc.environ = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add, 0);
add = args_next_value(&value);
}
sc.idx = -1;
@ -81,9 +86,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
if (spawn_pane(&sc, &cause) == NULL) {
cmdq_error(item, "respawn pane failed: %s", cause);
free(cause);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
@ -91,8 +93,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,9 +34,9 @@ const struct cmd_entry cmd_respawn_window_entry = {
.name = "respawn-window",
.alias = "respawnw",
.args = { "c:e:kt:", 0, -1, NULL },
.args = { "c:e:kt:", 0, -1 },
.usage = "[-k] [-c start-directory] [-e environment] "
CMD_TARGET_WINDOW_USAGE " [shell-command [argument ...]]",
CMD_TARGET_WINDOW_USAGE " [command]",
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -49,25 +49,29 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct spawn_context sc = { 0 };
struct spawn_context sc;
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
char *cause = NULL;
struct args_value *av;
const char *add;
struct args_value *value;
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.wl = wl;
sc.tc = tc;
args_to_vector(args, &sc.argc, &sc.argv);
sc.name = NULL;
sc.argc = args->argc;
sc.argv = args->argv;
sc.environ = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add, 0);
add = args_next_value(&value);
}
sc.idx = -1;
@ -80,16 +84,11 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
if (spawn_window(&sc, &cause) == NULL) {
cmdq_error(item, "respawn window failed: %s", cause);
free(cause);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
server_redraw_window(wl->window);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_NORMAL);
}

View File

@ -31,7 +31,7 @@ const struct cmd_entry cmd_rotate_window_entry = {
.name = "rotate-window",
.alias = "rotatew",
.args = { "Dt:UZ", 0, 0, NULL },
.args = { "Dt:UZ", 0, 0 },
.usage = "[-DUZ] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },

View File

@ -30,10 +30,7 @@
* Runs a command without a window.
*/
static enum args_parse_type cmd_run_shell_args_parse(struct args *, u_int,
char **);
static enum cmd_retval cmd_run_shell_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmdq_item *);
static void cmd_run_shell_timer(int, short, void *);
static void cmd_run_shell_callback(struct job *);
@ -44,9 +41,8 @@ const struct cmd_entry cmd_run_shell_entry = {
.name = "run-shell",
.alias = "run",
.args = { "bd:Ct:Es:c:", 0, 1, cmd_run_shell_args_parse },
.usage = "[-bCE] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE
" [shell-command]",
.args = { "bd:Ct:", 0, 1 },
.usage = "[-bC] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -55,26 +51,18 @@ const struct cmd_entry cmd_run_shell_entry = {
};
struct cmd_run_shell_data {
struct client *client;
char *cmd;
struct args_command_state *state;
char *cwd;
struct cmdq_item *item;
struct session *s;
int wp_id;
struct event timer;
int flags;
struct client *client;
char *cmd;
int shell;
char *cwd;
struct cmdq_item *item;
struct session *s;
int wp_id;
struct event timer;
int flags;
struct cmd_parse_input pi;
};
static enum args_parse_type
cmd_run_shell_args_parse(struct args *args, __unused u_int idx,
__unused char **cause)
{
if (args_has(args, 'C'))
return (ARGS_PARSE_COMMANDS_OR_STRING);
return (ARGS_PARSE_STRING);
}
static void
cmd_run_shell_print(struct job *job, const char *msg)
{
@ -90,10 +78,9 @@ cmd_run_shell_print(struct job *job, const char *msg)
cmdq_print(cdata->item, "%s", msg);
return;
}
if (cdata->item != NULL && cdata->client != NULL)
wp = server_client_get_pane(cdata->client);
if (wp == NULL && cmd_find_from_nothing(&fs, 0) == 0)
wp = fs.wp;
if (cmd_find_from_nothing(&fs, 0) != 0)
return;
wp = fs.wp;
if (wp == NULL)
return;
}
@ -101,7 +88,7 @@ cmd_run_shell_print(struct job *job, const char *msg)
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode != &window_view_mode)
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
window_copy_add(wp, 1, "%s", msg);
window_copy_add(wp, "%s", msg);
}
static enum cmd_retval
@ -110,11 +97,10 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct cmd_run_shell_data *cdata;
struct client *c = cmdq_get_client(item);
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct window_pane *wp = target->wp;
const char *delay, *cmd;
const char *delay;
double d;
struct timeval tv;
char *end;
@ -126,17 +112,21 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "invalid delay time: %s", delay);
return (CMD_RETURN_ERROR);
}
} else if (args_count(args) == 0)
} else if (args->argc == 0)
return (CMD_RETURN_NORMAL);
cdata = xcalloc(1, sizeof *cdata);
if (!args_has(args, 'C')) {
cmd = args_string(args, 0);
if (cmd != NULL)
cdata->cmd = format_single_from_target(item, cmd);
} else {
cdata->state = args_make_commands_prepare(self, item, 0, NULL,
wait, 1);
if (args->argc != 0)
cdata->cmd = format_single_from_target(item, args->argv[0]);
cdata->shell = !args_has(args, 'C');
if (!cdata->shell) {
memset(&cdata->pi, 0, sizeof cdata->pi);
cmd_get_source(self, &cdata->pi.file, &cdata->pi.line);
if (wait)
cdata->pi.item = item;
cdata->pi.c = tc;
cmd_find_copy_state(&cdata->pi.fs, target);
}
if (args_has(args, 't') && wp != NULL)
@ -145,7 +135,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
cdata->wp_id = -1;
if (wait) {
cdata->client = c;
cdata->client = cmdq_get_client(item);
cdata->item = item;
} else {
cdata->client = tc;
@ -153,13 +143,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
}
if (cdata->client != NULL)
cdata->client->references++;
if (args_has(args, 'c'))
cdata->cwd = xstrdup(args_get(args, 'c'));
else
cdata->cwd = xstrdup(server_client_get_cwd(c, s));
if (args_has(args, 'E'))
cdata->flags |= JOB_SHOWSTDERR;
cdata->cwd = xstrdup(server_client_get_cwd(cmdq_get_client(item), s));
cdata->s = s;
if (s != NULL)
@ -185,38 +170,34 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
struct cmd_run_shell_data *cdata = arg;
struct client *c = cdata->client;
const char *cmd = cdata->cmd;
struct cmdq_item *item = cdata->item, *new_item;
struct cmd_list *cmdlist;
char *error;
struct cmdq_item *item = cdata->item;
enum cmd_parse_status status;
if (cdata->state == NULL) {
if (cmd == NULL) {
if (cdata->item != NULL)
cmdq_continue(cdata->item);
cmd_run_shell_free(cdata);
return;
}
if (job_run(cmd, 0, NULL, NULL, cdata->s, cdata->cwd, NULL,
if (cmd != NULL && cdata->shell) {
if (job_run(cmd, 0, NULL, cdata->s, cdata->cwd, NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata,
cdata->flags, -1, -1) == NULL)
cmd_run_shell_free(cdata);
return;
}
cmdlist = args_make_commands(cdata->state, 0, NULL, &error);
if (cmdlist == NULL) {
if (cdata->item == NULL) {
*error = toupper((u_char)*error);
status_message_set(c, -1, 1, 0, 0, "%s", error);
} else
cmdq_error(cdata->item, "%s", error);
free(error);
} else if (item == NULL) {
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
} else {
new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
cmdq_insert_after(item, new_item);
if (cmd != NULL) {
if (item != NULL) {
status = cmd_parse_and_insert(cmd, &cdata->pi, item,
cmdq_get_state(item), &error);
} else {
status = cmd_parse_and_append(cmd, &cdata->pi, c, NULL,
&error);
}
if (status == CMD_PARSE_ERROR) {
if (cdata->item == NULL) {
*error = toupper((u_char)*error);
status_message_set(c, -1, 1, 0, "%s", error);
} else
cmdq_error(cdata->item, "%s", error);
free(error);
}
}
if (cdata->item != NULL)
@ -235,8 +216,7 @@ cmd_run_shell_callback(struct job *job)
int retcode, status;
do {
line = evbuffer_readln(event->input, NULL, EVBUFFER_EOL_LF);
if (line != NULL) {
if ((line = evbuffer_readline(event->input)) != NULL) {
cmd_run_shell_print(job, line);
free(line);
}
@ -285,8 +265,6 @@ cmd_run_shell_free(void *data)
session_remove_ref(cdata->s, __func__);
if (cdata->client != NULL)
server_client_unref(cdata->client);
if (cdata->state != NULL)
args_make_commands_free(cdata->state);
free(cdata->cwd);
free(cdata->cmd);
free(cdata);

View File

@ -37,7 +37,7 @@ const struct cmd_entry cmd_save_buffer_entry = {
.name = "save-buffer",
.alias = "saveb",
.args = { "ab:", 1, 1, NULL },
.args = { "ab:", 1, 1 },
.usage = "[-a] " CMD_BUFFER_USAGE " path",
.flags = CMD_AFTERHOOK,
@ -48,7 +48,7 @@ const struct cmd_entry cmd_show_buffer_entry = {
.name = "show-buffer",
.alias = "showb",
.args = { "b:", 0, 0, NULL },
.args = { "b:", 0, 0 },
.usage = CMD_BUFFER_USAGE,
.flags = CMD_AFTERHOOK,
@ -78,8 +78,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
int flags;
const char *bufname = args_get(args, 'b'), *bufdata;
size_t bufsize;
char *path;
struct evbuffer *evb;
char *path, *tmp;
if (bufname == NULL) {
if ((pb = paste_get_top(NULL)) == NULL) {
@ -97,17 +96,15 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
if (cmd_get_entry(self) == &cmd_show_buffer_entry) {
if (c->session != NULL || (c->flags & CLIENT_CONTROL)) {
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
evbuffer_add(evb, bufdata, bufsize);
cmdq_print_data(item, evb);
evbuffer_free(evb);
utf8_stravisx(&tmp, bufdata, bufsize,
VIS_OCTAL|VIS_CSTYLE|VIS_TAB);
cmdq_print(item, "%s", tmp);
free(tmp);
return (CMD_RETURN_NORMAL);
}
path = xstrdup("-");
} else
path = format_single_from_target(item, args_string(args, 0));
path = format_single_from_target(item, args->argv[0]);
if (args_has(args, 'a'))
flags = O_APPEND;
else

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_layout_entry = {
.name = "select-layout",
.alias = "selectl",
.args = { "Enopt:", 0, 1, NULL },
.args = { "Enopt:", 0, 1 },
.usage = "[-Enop] " CMD_TARGET_PANE_USAGE " [layout-name]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_next_layout_entry = {
.name = "next-layout",
.alias = "nextl",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -59,7 +59,7 @@ const struct cmd_entry cmd_previous_layout_entry = {
.name = "previous-layout",
.alias = "prevl",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -77,7 +77,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
struct window *w = wl->window;
struct window_pane *wp = target->wp;
const char *layoutname;
char *oldlayout, *cause;
char *oldlayout;
int next, previous, layout;
server_unzoom_window(w);
@ -105,28 +105,27 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
goto changed;
}
if (args_count(args) != 0)
layoutname = args_string(args, 0);
else if (args_has(args, 'o'))
layoutname = oldlayout;
else
layoutname = NULL;
if (!args_has(args, 'o')) {
if (layoutname == NULL)
if (args->argc == 0)
layout = w->lastlayout;
else
layout = layout_set_lookup(layoutname);
layout = layout_set_lookup(args->argv[0]);
if (layout != -1) {
layout_set_select(w, layout);
goto changed;
}
}
if (args->argc != 0)
layoutname = args->argv[0];
else if (args_has(args, 'o'))
layoutname = oldlayout;
else
layoutname = NULL;
if (layoutname != NULL) {
if (layout_parse(w, layoutname, &cause) == -1) {
cmdq_error(item, "%s: %s", cause, layoutname);
free(cause);
if (layout_parse(w, layoutname) == -1) {
cmdq_error(item, "can't set layout: %s", layoutname);
goto error;
}
goto changed;

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_pane_entry = {
.name = "select-pane",
.alias = "selectp",
.args = { "DdegLlMmP:RT:t:UZ", 0, 0, NULL }, /* -P and -g deprecated */
.args = { "DdegLlMmP:RT:t:UZ", 0, 0 }, /* -P and -g deprecated */
.usage = "[-DdeLlMmRUZ] [-T title] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_last_pane_entry = {
.name = "last-pane",
.alias = "lastp",
.args = { "det:Z", 0, 0, NULL },
.args = { "det:Z", 0, 0 },
.usage = "[-deZ] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -98,11 +98,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
struct options_entry *o;
if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
/*
* Check for no last pane found in case the other pane was
* spawned without being visited (for example split-window -d).
*/
lastwp = TAILQ_FIRST(&w->last_panes);
lastwp = w->last;
if (lastwp == NULL && window_count_panes(w) == 2) {
lastwp = TAILQ_PREV(w->active, window_panes, entry);
if (lastwp == NULL)
@ -149,14 +145,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
markedwp = marked_pane.wp;
if (lastwp != NULL) {
lastwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
server_redraw_window_borders(lastwp->window);
server_status_window(lastwp->window);
}
if (markedwp != NULL) {
markedwp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
server_redraw_window_borders(markedwp->window);
server_status_window(markedwp->window);
}
@ -171,7 +163,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
options_set_string(oo, "window-active-style", 0, "%s", style);
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|PANE_THEMECHANGED);
wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED);
}
if (args_has(args, 'g')) {
cmdq_print(item, "%s", options_get_string(oo, "window-style"));

View File

@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_window_entry = {
.name = "select-window",
.alias = "selectw",
.args = { "lnpTt:", 0, 0, NULL },
.args = { "lnpTt:", 0, 0 },
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
.target = { 't', CMD_FIND_WINDOW, 0 },
@ -46,7 +46,7 @@ const struct cmd_entry cmd_next_window_entry = {
.name = "next-window",
.alias = "next",
.args = { "at:", 0, 0, NULL },
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -59,7 +59,7 @@ const struct cmd_entry cmd_previous_window_entry = {
.name = "previous-window",
.alias = "prev",
.args = { "at:", 0, 0, NULL },
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@ -72,7 +72,7 @@ const struct cmd_entry cmd_last_window_entry = {
.name = "last-window",
.alias = "last",
.args = { "t:", 0, 0, NULL },
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },

View File

@ -33,13 +33,13 @@ const struct cmd_entry cmd_send_keys_entry = {
.name = "send-keys",
.alias = "send",
.args = { "c:FHKlMN:Rt:X", 0, -1, NULL },
.usage = "[-FHKlMRX] [-c target-client] [-N repeat-count] "
CMD_TARGET_PANE_USAGE " [key ...]",
.args = { "FHlMN:Rt:X", 0, -1 },
.usage = "[-FHlMRX] [-N repeat-count] " CMD_TARGET_PANE_USAGE
" key ...",
.target = { 't', CMD_FIND_PANE, 0 },
.flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL,
.flags = CMD_AFTERHOOK,
.exec = cmd_send_keys_exec
};
@ -47,7 +47,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
.name = "send-prefix",
.alias = NULL,
.args = { "2t:", 0, 0, NULL },
.args = { "2t:", 0, 0 },
.usage = "[-2] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@ -58,7 +58,7 @@ const struct cmd_entry cmd_send_prefix_entry = {
static struct cmdq_item *
cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
struct args *args, key_code key)
key_code key)
{
struct cmd_find_state *target = cmdq_get_target(item);
struct client *tc = cmdq_get_target_client(item);
@ -66,22 +66,8 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
struct winlink *wl = target->wl;
struct window_pane *wp = target->wp;
struct window_mode_entry *wme;
struct key_table *table = NULL;
struct key_table *table;
struct key_binding *bd;
struct key_event *event;
if (args_has(args, 'K')) {
if (tc == NULL)
return (item);
event = xcalloc(1, sizeof *event);
event->key = key|KEYC_SENT;
memset(&event->m, 0, sizeof event->m);
if (server_client_handle_key(tc, event) == 0) {
free(event->buf);
free(event);
}
return (item);
}
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode->key_table == NULL) {
@ -104,7 +90,7 @@ static struct cmdq_item *
cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after,
struct args *args, int i)
{
const char *s = args_string(args, i);
const char *s = args->argv[i];
struct utf8_data *ud, *loop;
utf8_char uc;
key_code key;
@ -116,16 +102,14 @@ cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after,
n = strtol(s, &endptr, 16);
if (*s =='\0' || n < 0 || n > 0xff || *endptr != '\0')
return (item);
return (cmd_send_keys_inject_key(item, after, args,
KEYC_LITERAL|n));
return (cmd_send_keys_inject_key(item, after, KEYC_LITERAL|n));
}
literal = args_has(args, 'l');
if (!literal) {
key = key_string_lookup_string(s);
if (key != KEYC_NONE && key != KEYC_UNKNOWN) {
after = cmd_send_keys_inject_key(item, after, args,
key);
after = cmd_send_keys_inject_key(item, after, key);
if (after != NULL)
return (after);
}
@ -141,8 +125,7 @@ cmd_send_keys_inject_string(struct cmdq_item *item, struct cmdq_item *after,
continue;
key = uc;
}
after = cmd_send_keys_inject_key(item, after, args,
key);
after = cmd_send_keys_inject_key(item, after, key);
}
free(ud);
}
@ -162,20 +145,19 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
struct mouse_event *m = &event->m;
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
struct cmdq_item *after = item;
int i;
key_code key;
u_int i, np = 1;
u_int count = args_count(args);
u_int np = 1;
char *cause = NULL;
if (args_has(args, 'N')) {
np = args_strtonum_and_expand(args, 'N', 1, UINT_MAX, item,
&cause);
np = args_strtonum(args, 'N', 1, UINT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "repeat count %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (wme != NULL && (args_has(args, 'X') || count == 0)) {
if (wme != NULL && (args_has(args, 'X') || args->argc == 0)) {
if (wme->mode->command == NULL) {
cmdq_error(item, "not in a mode");
return (CMD_RETURN_ERROR);
@ -210,26 +192,17 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
key = options_get_number(s->options, "prefix2");
else
key = options_get_number(s->options, "prefix");
cmd_send_keys_inject_key(item, item, args, key);
cmd_send_keys_inject_key(item, item, key);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'R')) {
colour_palette_clear(&wp->palette);
window_pane_reset_palette(wp);
input_reset(wp->ictx, 1);
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED|PANE_REDRAW);
}
if (count == 0) {
if (args_has(args, 'N') || args_has(args, 'R'))
return (CMD_RETURN_NORMAL);
for (; np != 0; np--)
cmd_send_keys_inject_key(item, NULL, args, event->key);
return (CMD_RETURN_NORMAL);
}
for (; np != 0; np--) {
for (i = 0; i < count; i++) {
for (i = 0; i < args->argc; i++) {
after = cmd_send_keys_inject_string(item, after, args,
i);
}

View File

@ -1,147 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2021 Dallas Lyons <dallasdlyons@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
* 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/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
/*
* Controls access to session.
*/
static enum cmd_retval cmd_server_access_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_server_access_entry = {
.name = "server-access",
.alias = NULL,
.args = { "adlrw", 0, 1, NULL },
.usage = "[-adlrw] " CMD_TARGET_PANE_USAGE " [user]",
.flags = CMD_CLIENT_CANFAIL,
.exec = cmd_server_access_exec
};
static enum cmd_retval
cmd_server_access_deny(struct cmdq_item *item, struct passwd *pw)
{
struct client *loop;
struct server_acl_user *user;
uid_t uid;
if ((user = server_acl_user_find(pw->pw_uid)) == NULL) {
cmdq_error(item, "user %s not found", pw->pw_name);
return (CMD_RETURN_ERROR);
}
TAILQ_FOREACH(loop, &clients, entry) {
uid = proc_get_peer_uid(loop->peer);
if (uid == server_acl_get_uid(user)) {
loop->exit_message = xstrdup("access not allowed");
loop->flags |= CLIENT_EXIT;
}
}
server_acl_user_deny(pw->pw_uid);
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_target_client(item);
char *name;
struct passwd *pw = NULL;
if (args_has(args, 'l')) {
server_acl_display(item);
return (CMD_RETURN_NORMAL);
}
if (args_count(args) == 0) {
cmdq_error(item, "missing user argument");
return (CMD_RETURN_ERROR);
}
name = format_single(item, args_string(args, 0), c, NULL, NULL, NULL);
if (*name != '\0')
pw = getpwnam(name);
if (pw == NULL) {
cmdq_error(item, "unknown user: %s", name);
return (CMD_RETURN_ERROR);
}
free(name);
if (pw->pw_uid == 0 || pw->pw_uid == getuid()) {
cmdq_error(item, "%s owns the server, can't change access",
pw->pw_name);
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'a') && args_has(args, 'd')) {
cmdq_error(item, "-a and -d cannot be used together");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'w') && args_has(args, 'r')) {
cmdq_error(item, "-r and -w cannot be used together");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'd'))
return (cmd_server_access_deny(item, pw));
if (args_has(args, 'a')) {
if (server_acl_user_find(pw->pw_uid) != NULL) {
cmdq_error(item, "user %s is already added",
pw->pw_name);
return (CMD_RETURN_ERROR);
}
server_acl_user_allow(pw->pw_uid);
/* Do not return - allow -r or -w with -a. */
} else if (args_has(args, 'r') || args_has(args, 'w')) {
/* -r or -w implies -a if user does not exist. */
if (server_acl_user_find(pw->pw_uid) == NULL)
server_acl_user_allow(pw->pw_uid);
}
if (args_has(args, 'w')) {
if (server_acl_user_find(pw->pw_uid) == NULL) {
cmdq_error(item, "user %s not found", pw->pw_name);
return (CMD_RETURN_ERROR);
}
server_acl_user_allow_write(pw->pw_uid);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'r')) {
if (server_acl_user_find(pw->pw_uid) == NULL) {
cmdq_error(item, "user %s not found", pw->pw_name);
return (CMD_RETURN_ERROR);
}
server_acl_user_deny_write(pw->pw_uid);
return (CMD_RETURN_NORMAL);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -33,9 +33,9 @@ const struct cmd_entry cmd_set_buffer_entry = {
.name = "set-buffer",
.alias = "setb",
.args = { "ab:t:n:w", 0, 1, NULL },
.args = { "ab:t:n:w", 0, 1 },
.usage = "[-aw] " CMD_BUFFER_USAGE " [-n new-buffer-name] "
CMD_TARGET_CLIENT_USAGE " [data]",
CMD_TARGET_CLIENT_USAGE " data",
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL,
.exec = cmd_set_buffer_exec
@ -45,7 +45,7 @@ const struct cmd_entry cmd_delete_buffer_entry = {
.name = "delete-buffer",
.alias = "deleteb",
.args = { "b:", 0, 0, NULL },
.args = { "b:", 0, 0 },
.usage = CMD_BUFFER_USAGE,
.flags = CMD_AFTERHOOK,
@ -69,13 +69,8 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
pb = paste_get_name(bufname);
if (cmd_get_entry(self) == &cmd_delete_buffer_entry) {
if (pb == NULL) {
if (bufname != NULL) {
cmdq_error(item, "unknown buffer: %s", bufname);
return (CMD_RETURN_ERROR);
}
if (pb == NULL)
pb = paste_get_top(&bufname);
}
if (pb == NULL) {
cmdq_error(item, "no buffer");
return (CMD_RETURN_ERROR);
@ -85,13 +80,8 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
}
if (args_has(args, 'n')) {
if (pb == NULL) {
if (bufname != NULL) {
cmdq_error(item, "unknown buffer: %s", bufname);
return (CMD_RETURN_ERROR);
}
if (pb == NULL)
pb = paste_get_top(&bufname);
}
if (pb == NULL) {
cmdq_error(item, "no buffer");
return (CMD_RETURN_ERROR);
@ -104,11 +94,11 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_count(args) != 1) {
if (args->argc != 1) {
cmdq_error(item, "no data specified");
return (CMD_RETURN_ERROR);
}
if ((newsize = strlen(args_string(args, 0))) == 0)
if ((newsize = strlen(args->argv[0])) == 0)
return (CMD_RETURN_NORMAL);
bufsize = 0;
@ -121,7 +111,7 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
}
bufdata = xrealloc(bufdata, bufsize + newsize);
memcpy(bufdata + bufsize, args_string(args, 0), newsize);
memcpy(bufdata + bufsize, args->argv[0], newsize);
bufsize += newsize;
if (paste_set(bufdata, bufsize, bufname, &cause) != 0) {
@ -131,7 +121,7 @@ cmd_set_buffer_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'w') && tc != NULL)
tty_set_selection(&tc->tty, "", bufdata, bufsize);
tty_set_selection(&tc->tty, bufdata, bufsize);
return (CMD_RETURN_NORMAL);
}

View File

@ -34,8 +34,8 @@ const struct cmd_entry cmd_set_environment_entry = {
.name = "set-environment",
.alias = "setenv",
.args = { "Fhgrt:u", 1, 2, NULL },
.usage = "[-Fhgru] " CMD_TARGET_SESSION_USAGE " variable [value]",
.args = { "Fhgrt:u", 1, 2 },
.usage = "[-Fhgru] " CMD_TARGET_SESSION_USAGE " name [value]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@ -49,11 +49,11 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct environ *env;
const char *name = args_string(args, 0), *value;
const char *tflag;
char *expanded = NULL;
const char *name, *value, *tflag;
char *expand = NULL;
enum cmd_retval retval = CMD_RETURN_NORMAL;
name = args->argv[0];
if (*name == '\0') {
cmdq_error(item, "empty variable name");
return (CMD_RETURN_ERROR);
@ -63,14 +63,13 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
if (args_count(args) < 2)
if (args->argc < 2)
value = NULL;
else if (args_has(args, 'F'))
value = expand = format_single_from_target(item, args->argv[1]);
else
value = args_string(args, 1);
if (value != NULL && args_has(args, 'F')) {
expanded = format_single_from_target(item, value);
value = expanded;
}
value = args->argv[1];
if (args_has(args, 'g'))
env = global_environ;
else {
@ -114,6 +113,6 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
}
out:
free(expanded);
free(expand);
return (retval);
}

View File

@ -27,16 +27,13 @@
* Set an option.
*/
static enum args_parse_type cmd_set_option_args_parse(struct args *,
u_int, char **);
static enum cmd_retval cmd_set_option_exec(struct cmd *,
struct cmdq_item *);
static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_set_option_entry = {
.name = "set-option",
.alias = "set",
.args = { "aFgopqst:uUw", 1, 2, cmd_set_option_args_parse },
.args = { "aFgopqst:uUw", 1, 2 },
.usage = "[-aFgopqsuUw] " CMD_TARGET_PANE_USAGE " option [value]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -49,7 +46,7 @@ const struct cmd_entry cmd_set_window_option_entry = {
.name = "set-window-option",
.alias = "setw",
.args = { "aFgoqt:u", 1, 2, cmd_set_option_args_parse },
.args = { "aFgoqt:u", 1, 2 },
.usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@ -62,7 +59,7 @@ const struct cmd_entry cmd_set_hook_entry = {
.name = "set-hook",
.alias = NULL,
.args = { "agpRt:uw", 1, 2, cmd_set_option_args_parse },
.args = { "agpRt:uw", 1, 2 },
.usage = "[-agpRuw] " CMD_TARGET_PANE_USAGE " hook [command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -71,15 +68,6 @@ const struct cmd_entry cmd_set_hook_entry = {
.exec = cmd_set_option_exec
};
static enum args_parse_type
cmd_set_option_args_parse(__unused struct args *args, u_int idx,
__unused char **cause)
{
if (idx == 1)
return (ARGS_PARSE_COMMANDS_OR_STRING);
return (ARGS_PARSE_STRING);
}
static enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
{
@ -89,16 +77,14 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
struct window_pane *loop;
struct options *oo;
struct options_entry *parent, *o, *po;
char *name, *argument, *expanded = NULL;
char *cause;
const char *value;
char *name, *argument, *value = NULL, *cause;
int window, idx, already, error, ambiguous;
int scope;
window = (cmd_get_entry(self) == &cmd_set_window_option_entry);
/* Expand argument. */
argument = format_single_from_target(item, args_string(args, 0));
argument = format_single_from_target(item, args->argv[0]);
/* If set-hook -R, fire the hook straight away. */
if (cmd_get_entry(self) == &cmd_set_hook_entry && args_has(args, 'R')) {
@ -118,14 +104,12 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
if (args_count(args) < 2)
if (args->argc < 2)
value = NULL;
else if (args_has(args, 'F'))
value = format_single_from_target(item, args->argv[1]);
else
value = args_string(args, 1);
if (value != NULL && args_has(args, 'F')) {
expanded = format_single_from_target(item, value);
value = expanded;
}
value = xstrdup(args->argv[1]);
/* Get the scope and table for the option .*/
scope = options_scope_from_name(args, window, name, target, &oo,
@ -227,13 +211,13 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
out:
free(argument);
free(expanded);
free(value);
free(name);
return (CMD_RETURN_NORMAL);
fail:
free(argument);
free(expanded);
free(value);
free(name);
return (CMD_RETURN_ERROR);
}

View File

@ -38,8 +38,8 @@ const struct cmd_entry cmd_show_environment_entry = {
.name = "show-environment",
.alias = "showenv",
.args = { "hgst:", 0, 1, NULL },
.usage = "[-hgs] " CMD_TARGET_SESSION_USAGE " [variable]",
.args = { "hgst:", 0, 1 },
.usage = "[-hgs] " CMD_TARGET_SESSION_USAGE " [name]",
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
@ -101,7 +101,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_find_state *target = cmdq_get_target(item);
struct environ *env;
struct environ_entry *envent;
const char *tflag, *name = args_string(args, 0);
const char *tflag;
if ((tflag = args_get(args, 't')) != NULL) {
if (target->s == NULL) {
@ -124,10 +124,10 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
env = target->s->environ;
}
if (name != NULL) {
envent = environ_find(env, name);
if (args->argc != 0) {
envent = environ_find(env, args->argv[0]);
if (envent == NULL) {
cmdq_error(item, "unknown variable: %s", name);
cmdq_error(item, "unknown variable: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
cmd_show_environment_print(self, item, envent);

View File

@ -38,7 +38,7 @@ const struct cmd_entry cmd_show_messages_entry = {
.name = "show-messages",
.alias = "showmsgs",
.args = { "JTt:", 0, 0, NULL },
.args = { "JTt:", 0, 0 },
.usage = "[-JT] " CMD_TARGET_CLIENT_USAGE,
.flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG,

View File

@ -38,7 +38,7 @@ const struct cmd_entry cmd_show_options_entry = {
.name = "show-options",
.alias = "show",
.args = { "AgHpqst:vw", 0, 1, NULL },
.args = { "AgHpqst:vw", 0, 1 },
.usage = "[-AgHpqsvw] " CMD_TARGET_PANE_USAGE " [option]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -51,7 +51,7 @@ const struct cmd_entry cmd_show_window_options_entry = {
.name = "show-window-options",
.alias = "showw",
.args = { "gvt:", 0, 1, NULL },
.args = { "gvt:", 0, 1 },
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
@ -64,8 +64,8 @@ const struct cmd_entry cmd_show_hooks_entry = {
.name = "show-hooks",
.alias = NULL,
.args = { "gpt:w", 0, 1, NULL },
.usage = "[-gpw] " CMD_TARGET_PANE_USAGE " [hook]",
.args = { "gpt:w", 0, 1 },
.usage = "[-gpw] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -85,7 +85,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
window = (cmd_get_entry(self) == &cmd_show_window_options_entry);
if (args_count(args) == 0) {
if (args->argc == 0) {
scope = options_scope_from_flags(args, window, target, &oo,
&cause);
if (scope == OPTIONS_TABLE_NONE) {
@ -97,12 +97,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
}
return (cmd_show_options_all(self, item, scope, oo));
}
argument = format_single_from_target(item, args_string(args, 0));
argument = format_single_from_target(item, args->argv[0]);
name = options_match(argument, &idx, &ambiguous);
if (name == NULL) {
if (args_has(args, 'q'))
goto out;
goto fail;
if (ambiguous)
cmdq_error(item, "ambiguous option: %s", argument);
else
@ -113,7 +113,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
&cause);
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
goto out;
goto fail;
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
@ -126,14 +126,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
parent = 0;
if (o != NULL)
cmd_show_options_print(self, item, o, idx, parent);
else if (*name == '@') {
if (args_has(args, 'q'))
goto out;
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
out:
free(name);
free(argument);
return (CMD_RETURN_NORMAL);

View File

@ -1,108 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2021 Anindya Mukherjee <anindya49@hotmail.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "tmux.h"
#include <stdlib.h>
/*
* Show or clear prompt history.
*/
static enum cmd_retval cmd_show_prompt_history_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_show_prompt_history_entry = {
.name = "show-prompt-history",
.alias = "showphist",
.args = { "T:", 0, 0, NULL },
.usage = "[-T prompt-type]",
.flags = CMD_AFTERHOOK,
.exec = cmd_show_prompt_history_exec
};
const struct cmd_entry cmd_clear_prompt_history_entry = {
.name = "clear-prompt-history",
.alias = "clearphist",
.args = { "T:", 0, 0, NULL },
.usage = "[-T prompt-type]",
.flags = CMD_AFTERHOOK,
.exec = cmd_show_prompt_history_exec
};
static enum cmd_retval
cmd_show_prompt_history_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
const char *typestr = args_get(args, 'T');
enum prompt_type type;
u_int tidx, hidx;
if (cmd_get_entry(self) == &cmd_clear_prompt_history_entry) {
if (typestr == NULL) {
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
free(status_prompt_hlist[tidx]);
status_prompt_hlist[tidx] = NULL;
status_prompt_hsize[tidx] = 0;
}
} else {
type = status_prompt_type(typestr);
if (type == PROMPT_TYPE_INVALID) {
cmdq_error(item, "invalid type: %s", typestr);
return (CMD_RETURN_ERROR);
}
free(status_prompt_hlist[type]);
status_prompt_hlist[type] = NULL;
status_prompt_hsize[type] = 0;
}
return (CMD_RETURN_NORMAL);
}
if (typestr == NULL) {
for (tidx = 0; tidx < PROMPT_NTYPES; tidx++) {
cmdq_print(item, "History for %s:\n",
status_prompt_type_string(tidx));
for (hidx = 0; hidx < status_prompt_hsize[tidx];
hidx++) {
cmdq_print(item, "%d: %s", hidx + 1,
status_prompt_hlist[tidx][hidx]);
}
cmdq_print(item, "%s", "");
}
} else {
type = status_prompt_type(typestr);
if (type == PROMPT_TYPE_INVALID) {
cmdq_error(item, "invalid type: %s", typestr);
return (CMD_RETURN_ERROR);
}
cmdq_print(item, "History for %s:\n",
status_prompt_type_string(type));
for (hidx = 0; hidx < status_prompt_hsize[type]; hidx++) {
cmdq_print(item, "%d: %s", hidx + 1,
status_prompt_hlist[type][hidx]);
}
cmdq_print(item, "%s", "");
}
return (CMD_RETURN_NORMAL);
}

View File

@ -29,19 +29,14 @@
* Sources a configuration file.
*/
#define CMD_SOURCE_FILE_DEPTH_LIMIT 50
static u_int cmd_source_file_depth;
static enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_source_file_entry = {
.name = "source-file",
.alias = "source",
.args = { "t:Fnqv", 1, -1, NULL },
.usage = "[-Fnqv] " CMD_TARGET_PANE_USAGE " path ...",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
.args = { "Fnqv", 1, -1 },
.usage = "[-Fnqv] path ...",
.flags = 0,
.exec = cmd_source_file_exec
@ -62,16 +57,6 @@ struct cmd_source_file_data {
static enum cmd_retval
cmd_source_file_complete_cb(struct cmdq_item *item, __unused void *data)
{
struct client *c = cmdq_get_client(item);
if (c == NULL) {
cmd_source_file_depth--;
log_debug("%s: depth now %u", __func__, cmd_source_file_depth);
} else {
c->source_file_depth--;
log_debug("%s: depth now %u", __func__, c->source_file_depth);
}
cfg_print_causes(item);
return (CMD_RETURN_NORMAL);
}
@ -80,19 +65,14 @@ static void
cmd_source_file_complete(struct client *c, struct cmd_source_file_data *cdata)
{
struct cmdq_item *new_item;
u_int i;
if (cfg_finished) {
if (cdata->retval == CMD_RETURN_ERROR &&
c != NULL &&
c->session == NULL)
if (cdata->retval == CMD_RETURN_ERROR && c->session == NULL)
c->retval = 1;
new_item = cmdq_get_callback(cmd_source_file_complete_cb, NULL);
cmdq_insert_after(cdata->after, new_item);
}
for (i = 0; i < cdata->nfiles; i++)
free(cdata->files[i]);
free(cdata->files);
free(cdata);
}
@ -107,7 +87,6 @@ cmd_source_file_done(struct client *c, const char *path, int error,
size_t bsize = EVBUFFER_LENGTH(buffer);
u_int n;
struct cmdq_item *new_item;
struct cmd_find_state *target = cmdq_get_target(item);
if (!closed)
return;
@ -116,7 +95,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
cmdq_error(item, "%s: %s", path, strerror(error));
else if (bsize != 0) {
if (load_cfg_from_buffer(bdata, bsize, path, c, cdata->after,
target, cdata->flags, &new_item) < 0)
cdata->flags, &new_item) < 0)
cdata->retval = CMD_RETURN_ERROR;
else if (new_item != NULL)
cdata->after = new_item;
@ -134,16 +113,7 @@ cmd_source_file_done(struct client *c, const char *path, int error,
static void
cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
{
char resolved[PATH_MAX];
if (realpath(path, resolved) == NULL) {
log_debug("%s: realpath(\"%s\") failed: %s", __func__,
path, strerror(errno));
} else
path = resolved;
log_debug("%s: %s", __func__, path);
cdata->files = xreallocarray(cdata->files, cdata->nfiles + 1,
sizeof *cdata->files);
cdata->files[cdata->nfiles++] = xstrdup(path);
@ -156,27 +126,11 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_source_file_data *cdata;
struct client *c = cmdq_get_client(item);
enum cmd_retval retval = CMD_RETURN_NORMAL;
char *pattern, *cwd, *expanded = NULL;
char *pattern, *cwd, *expand = NULL;
const char *path, *error;
glob_t g;
int result;
u_int i, j;
if (c == NULL) {
if (cmd_source_file_depth >= CMD_SOURCE_FILE_DEPTH_LIMIT) {
cmdq_error(item, "too many nested files");
return (CMD_RETURN_ERROR);
}
cmd_source_file_depth++;
log_debug("%s: depth now %u", __func__, cmd_source_file_depth);
} else {
if (c->source_file_depth >= CMD_SOURCE_FILE_DEPTH_LIMIT) {
cmdq_error(item, "too many nested files");
return (CMD_RETURN_ERROR);
}
c->source_file_depth++;
log_debug("%s: depth now %u", __func__, c->source_file_depth);
}
int i, result;
u_int j;
cdata = xcalloc(1, sizeof *cdata);
cdata->item = item;
@ -190,13 +144,13 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB);
for (i = 0; i < args_count(args); i++) {
path = args_string(args, i);
for (i = 0; i < args->argc; i++) {
if (args_has(args, 'F')) {
free(expanded);
expanded = format_single_from_target(item, path);
path = expanded;
}
free(expand);
expand = format_single_from_target(item, args->argv[i]);
path = expand;
} else
path = args->argv[i];
if (strcmp(path, "-") == 0) {
cmd_source_file_add(cdata, "-");
continue;
@ -220,17 +174,15 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "%s: %s", path, error);
retval = CMD_RETURN_ERROR;
}
globfree(&g);
free(pattern);
continue;
}
free(expand);
free(pattern);
for (j = 0; j < g.gl_pathc; j++)
cmd_source_file_add(cdata, g.gl_pathv[j]);
globfree(&g);
}
free(expanded);
cdata->after = item;
cdata->retval = retval;

View File

@ -39,10 +39,9 @@ const struct cmd_entry cmd_split_window_entry = {
.name = "split-window",
.alias = "splitw",
.args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL },
.args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1 },
.usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE
" [shell-command [argument ...]]",
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE " [command]",
.target = { 't', CMD_FIND_PANE, 0 },
@ -56,65 +55,70 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct cmd_find_state *current = cmdq_get_current(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct spawn_context sc = { 0 };
struct spawn_context sc;
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct window_pane *wp = target->wp, *new_wp;
enum layout_type type;
struct layout_cell *lc;
struct cmd_find_state fs;
int size, flags, input;
const char *template;
char *cause = NULL, *cp;
struct args_value *av;
u_int count = args_count(args), curval = 0;
int size, percentage, flags, input;
const char *template, *add, *errstr, *p;
char *cause, *cp, *copy;
size_t plen;
struct args_value *value;
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
else
type = LAYOUT_TOPBOTTOM;
if ((p = args_get(args, 'l')) != NULL) {
plen = strlen(p);
if (p[plen - 1] == '%') {
copy = xstrdup(p);
copy[plen - 1] = '\0';
percentage = strtonum(copy, 0, INT_MAX, &errstr);
free(copy);
if (errstr != NULL) {
cmdq_error(item, "percentage %s", errstr);
return (CMD_RETURN_ERROR);
}
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
size = (wp->sy * percentage) / 100;
else
curval = w->sx;
size = (wp->sx * percentage) / 100;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "lines %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
}
size = -1;
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, &cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
&cause);
if (cause == NULL)
size = curval * size / 100;
}
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "create pane failed: -p %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (type == LAYOUT_TOPBOTTOM)
size = (wp->sy * percentage) / 100;
else
size = (wp->sx * percentage) / 100;
} else
size = -1;
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
input = (args_has(args, 'I') && count == 0);
input = (args_has(args, 'I') && args->argc == 0);
flags = 0;
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
if (input || (count == 1 && *args_string(args, 0) == '\0'))
if (input || (args->argc == 1 && *args->argv[0] == '\0'))
flags |= SPAWN_EMPTY;
lc = layout_split_pane(wp, type, size, flags);
@ -123,6 +127,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
memset(&sc, 0, sizeof sc);
sc.item = item;
sc.s = s;
sc.wl = wl;
@ -130,13 +135,15 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
sc.wp0 = wp;
sc.lc = lc;
args_to_vector(args, &sc.argc, &sc.argv);
sc.name = NULL;
sc.argc = args->argc;
sc.argv = args->argv;
sc.environ = environ_create();
av = args_first_value(args, 'e');
while (av != NULL) {
environ_put(sc.environ, av->string, 0);
av = args_next_value(av);
add = args_first_value(args, 'e', &value);
while (add != NULL) {
environ_put(sc.environ, add, 0);
add = args_next_value(&value);
}
sc.idx = -1;
@ -151,27 +158,15 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
cmdq_error(item, "create pane failed: %s", cause);
free(cause);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
if (input) {
switch (window_pane_start_input(new_wp, item, &cause)) {
case -1:
server_client_remove_pane(new_wp);
layout_close_pane(new_wp);
window_remove_pane(wp->window, new_wp);
cmdq_error(item, "%s", cause);
free(cause);
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
case 1:
input = 0;
break;
}
if (input && window_pane_start_input(new_wp, item, &cause) != 0) {
server_client_remove_pane(new_wp);
layout_close_pane(new_wp);
window_remove_pane(wp->window, new_wp);
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (!args_has(args, 'd'))
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
@ -190,8 +185,6 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
cmdq_insert_hook(s, item, &fs, "after-split-window");
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
if (input)
return (CMD_RETURN_WAIT);

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_swap_pane_entry = {
.name = "swap-pane",
.alias = "swapp",
.args = { "dDs:t:UZ", 0, 0, NULL },
.args = { "dDs:t:UZ", 0, 0 },
.usage = "[-dDUZ] " CMD_SRCDST_PANE_USAGE,
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
@ -101,10 +101,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
src_wp->flags |= PANE_STYLECHANGED;
dst_wp->window = src_w;
options_set_parent(dst_wp->options, src_w->options);
dst_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
dst_wp->flags |= PANE_STYLECHANGED;
sx = src_wp->sx; sy = src_wp->sy;
xoff = src_wp->xoff; yoff = src_wp->yoff;
@ -128,20 +128,14 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
window_set_active_pane(dst_w, src_wp, 1);
}
if (src_w != dst_w) {
window_pane_stack_remove(&src_w->last_panes, src_wp);
window_pane_stack_remove(&dst_w->last_panes, dst_wp);
colour_palette_from_option(&src_wp->palette, src_wp->options);
colour_palette_from_option(&dst_wp->palette, dst_wp->options);
layout_fix_panes(src_w, NULL);
server_redraw_window(src_w);
if (src_w->last == src_wp)
src_w->last = NULL;
if (dst_w->last == dst_wp)
dst_w->last = NULL;
}
layout_fix_panes(dst_w, NULL);
server_redraw_window(src_w);
server_redraw_window(dst_w);
notify_window("window-layout-changed", src_w);
if (src_w != dst_w)
notify_window("window-layout-changed", dst_w);
out:
if (window_pop_zoom(src_w))
server_redraw_window(src_w);

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_swap_window_entry = {
.name = "swap-window",
.alias = "swapw",
.args = { "ds:t:", 0, 0, NULL },
.args = { "ds:t:", 0, 0 },
.usage = "[-d] " CMD_SRCDST_WINDOW_USAGE,
.source = { 's', CMD_FIND_WINDOW, CMD_FIND_DEFAULT_MARKED },

View File

@ -34,7 +34,7 @@ const struct cmd_entry cmd_switch_client_entry = {
.name = "switch-client",
.alias = "switchc",
.args = { "lc:EFnpt:rT:Z", 0, 0, NULL },
.args = { "lc:EFnpt:rT:Z", 0, 0 },
.usage = "[-ElnprZ] [-c target-client] [-t target-session] "
"[-T key-table]",
@ -134,9 +134,23 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
if (!args_has(args, 'E'))
environ_update(s->options, tc->environ, s->environ);
server_client_set_session(tc, s);
if (tc->session != NULL && tc->session != s)
tc->last_session = tc->session;
tc->session = s;
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
server_client_set_key_table(tc, NULL);
tty_update_client_offset(tc);
status_timer_start(tc);
notify_client("client-session-changed", tc);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_check_unattached();
server_redraw_client(tc);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
s->curw->window->latest = tc;
recalculate_sizes();
alerts_check_session(s);
return (CMD_RETURN_NORMAL);
}

View File

@ -32,7 +32,7 @@ const struct cmd_entry cmd_unbind_key_entry = {
.name = "unbind-key",
.alias = "unbind",
.args = { "anqT:", 0, 1, NULL },
.args = { "anqT:", 0, 1 },
.usage = "[-anq] [-T key-table] key",
.flags = CMD_AFTERHOOK,
@ -44,11 +44,11 @@ cmd_unbind_key_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
key_code key;
const char *tablename, *keystr = args_string(args, 0);
const char *tablename;
int quiet = args_has(args, 'q');
if (args_has(args, 'a')) {
if (keystr != NULL) {
if (args->argc != 0) {
if (!quiet)
cmdq_error(item, "key given with -a");
return (CMD_RETURN_ERROR);
@ -73,16 +73,16 @@ cmd_unbind_key_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (keystr == NULL) {
if (args->argc != 1) {
if (!quiet)
cmdq_error(item, "missing key");
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(keystr);
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
if (!quiet)
cmdq_error(item, "unknown key: %s", keystr);
cmdq_error(item, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}

View File

@ -34,7 +34,7 @@ const struct cmd_entry cmd_wait_for_entry = {
.name = "wait-for",
.alias = "wait",
.args = { "LSU", 1, 1, NULL },
.args = { "LSU", 1, 1 },
.usage = "[-L|-S|-U] channel",
.flags = 0,
@ -121,11 +121,11 @@ static enum cmd_retval
cmd_wait_for_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
const char *name = args_string(args, 0);
struct wait_channel *wc, find;
const char *name = args->argv[0];
struct wait_channel *wc, wc0;
find.name = name;
wc = RB_FIND(wait_channels, &wait_channels, &find);
wc0.name = name;
wc = RB_FIND(wait_channels, &wait_channels, &wc0);
if (args_has(args, 'S'))
return (cmd_wait_for_signal(item, name, wc));

135
cmd.c
View File

@ -35,7 +35,6 @@ extern const struct cmd_entry cmd_choose_buffer_entry;
extern const struct cmd_entry cmd_choose_client_entry;
extern const struct cmd_entry cmd_choose_tree_entry;
extern const struct cmd_entry cmd_clear_history_entry;
extern const struct cmd_entry cmd_clear_prompt_history_entry;
extern const struct cmd_entry cmd_clock_mode_entry;
extern const struct cmd_entry cmd_command_prompt_entry;
extern const struct cmd_entry cmd_confirm_before_entry;
@ -47,6 +46,7 @@ extern const struct cmd_entry cmd_display_menu_entry;
extern const struct cmd_entry cmd_display_message_entry;
extern const struct cmd_entry cmd_display_popup_entry;
extern const struct cmd_entry cmd_display_panes_entry;
extern const struct cmd_entry cmd_down_pane_entry;
extern const struct cmd_entry cmd_find_window_entry;
extern const struct cmd_entry cmd_has_session_entry;
extern const struct cmd_entry cmd_if_shell_entry;
@ -94,7 +94,6 @@ extern const struct cmd_entry cmd_select_pane_entry;
extern const struct cmd_entry cmd_select_window_entry;
extern const struct cmd_entry cmd_send_keys_entry;
extern const struct cmd_entry cmd_send_prefix_entry;
extern const struct cmd_entry cmd_server_access_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;
@ -105,7 +104,6 @@ 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_prompt_history_entry;
extern const struct cmd_entry cmd_show_window_options_entry;
extern const struct cmd_entry cmd_source_file_entry;
extern const struct cmd_entry cmd_split_window_entry;
@ -116,6 +114,7 @@ extern const struct cmd_entry cmd_swap_window_entry;
extern const struct cmd_entry cmd_switch_client_entry;
extern const struct cmd_entry cmd_unbind_key_entry;
extern const struct cmd_entry cmd_unlink_window_entry;
extern const struct cmd_entry cmd_up_pane_entry;
extern const struct cmd_entry cmd_wait_for_entry;
const struct cmd_entry *cmd_table[] = {
@ -127,7 +126,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_choose_client_entry,
&cmd_choose_tree_entry,
&cmd_clear_history_entry,
&cmd_clear_prompt_history_entry,
&cmd_clock_mode_entry,
&cmd_command_prompt_entry,
&cmd_confirm_before_entry,
@ -186,7 +184,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_select_window_entry,
&cmd_send_keys_entry,
&cmd_send_prefix_entry,
&cmd_server_access_entry,
&cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_hook_entry,
@ -197,7 +194,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_show_hooks_entry,
&cmd_show_messages_entry,
&cmd_show_options_entry,
&cmd_show_prompt_history_entry,
&cmd_show_window_options_entry,
&cmd_source_file_entry,
&cmd_split_window_entry,
@ -221,6 +217,10 @@ struct cmd {
char *file;
u_int line;
char *alias;
int argc;
char **argv;
TAILQ_ENTRY(cmd) qentry;
};
TAILQ_HEAD(cmds, cmd);
@ -247,7 +247,7 @@ cmd_log_argv(int argc, char **argv, const char *fmt, ...)
/* Prepend to an argument vector. */
void
cmd_prepend_argv(int *argc, char ***argv, const char *arg)
cmd_prepend_argv(int *argc, char ***argv, char *arg)
{
char **new_argv;
int i;
@ -264,7 +264,7 @@ cmd_prepend_argv(int *argc, char ***argv, const char *arg)
/* Append to an argument vector. */
void
cmd_append_argv(int *argc, char ***argv, const char *arg)
cmd_append_argv(int *argc, char ***argv, char *arg)
{
*argv = xreallocarray(*argv, (*argc) + 1, sizeof **argv);
(*argv)[(*argc)++] = xstrdup(arg);
@ -444,7 +444,7 @@ cmd_get_alias(const char *name)
}
/* Look up a command entry by name. */
const struct cmd_entry *
static const struct cmd_entry *
cmd_find(const char *name, char **cause)
{
const struct cmd_entry **loop, *entry, *found = NULL;
@ -495,32 +495,31 @@ ambiguous:
/* Parse a single command from an argument vector. */
struct cmd *
cmd_parse(struct args_value *values, u_int count, const char *file, u_int line,
char **cause)
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
{
const struct cmd_entry *entry;
const char *name;
struct cmd *cmd;
struct args *args;
char *error = NULL;
if (count == 0 || values[0].type != ARGS_STRING) {
if (argc == 0) {
xasprintf(cause, "no command");
return (NULL);
}
entry = cmd_find(values[0].string, cause);
name = argv[0];
entry = cmd_find(name, cause);
if (entry == NULL)
return (NULL);
cmd_log_argv(argc, argv, "%s: %s", __func__, entry->name);
args = args_parse(&entry->args, values, count, &error);
if (args == NULL && error == NULL) {
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
return (NULL);
}
if (args == NULL) {
xasprintf(cause, "command %s: %s", entry->name, error);
free(error);
return (NULL);
}
args = args_parse(entry->args.template, argc, argv);
if (args == NULL)
goto usage;
if (entry->args.lower != -1 && args->argc < entry->args.lower)
goto usage;
if (entry->args.upper != -1 && args->argc > entry->args.upper)
goto usage;
cmd = xcalloc(1, sizeof *cmd);
cmd->entry = entry;
@ -530,36 +529,32 @@ cmd_parse(struct args_value *values, u_int count, const char *file, u_int line,
cmd->file = xstrdup(file);
cmd->line = line;
cmd->alias = NULL;
cmd->argc = argc;
cmd->argv = cmd_copy_argv(argc, argv);
return (cmd);
usage:
if (args != NULL)
args_free(args);
xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
return (NULL);
}
/* Free a command. */
void
cmd_free(struct cmd *cmd)
{
free(cmd->alias);
cmd_free_argv(cmd->argc, cmd->argv);
free(cmd->file);
args_free(cmd->args);
free(cmd);
}
/* Copy a command. */
struct cmd *
cmd_copy(struct cmd *cmd, int argc, char **argv)
{
struct cmd *new_cmd;
new_cmd = xcalloc(1, sizeof *new_cmd);
new_cmd->entry = cmd->entry;
new_cmd->args = args_copy(cmd->args, argc, argv);
if (cmd->file != NULL)
new_cmd->file = xstrdup(cmd->file);
new_cmd->line = cmd->line;
return (new_cmd);
}
/* Get a command as a string. */
char *
cmd_print(struct cmd *cmd)
@ -598,18 +593,7 @@ cmd_list_append(struct cmd_list *cmdlist, struct cmd *cmd)
TAILQ_INSERT_TAIL(cmdlist->list, cmd, qentry);
}
/* Append all commands from one list to another. */
void
cmd_list_append_all(struct cmd_list *cmdlist, struct cmd_list *from)
{
struct cmd *cmd;
TAILQ_FOREACH(cmd, from->list, qentry)
cmd->group = cmdlist->group;
TAILQ_CONCAT(cmdlist->list, from->list, qentry);
}
/* Move all commands from one command list to another. */
/* Move all commands from one command list to another */
void
cmd_list_move(struct cmd_list *cmdlist, struct cmd_list *from)
{
@ -634,40 +618,9 @@ cmd_list_free(struct cmd_list *cmdlist)
free(cmdlist);
}
/* Copy a command list, expanding %s in arguments. */
struct cmd_list *
cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv)
{
struct cmd *cmd;
struct cmd_list *new_cmdlist;
struct cmd *new_cmd;
u_int group = cmdlist->group;
char *s;
s = cmd_list_print(cmdlist, 0);
log_debug("%s: %s", __func__, s);
free(s);
new_cmdlist = cmd_list_new();
TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
if (cmd->group != group) {
new_cmdlist->group = cmd_list_next_group++;
group = cmd->group;
}
new_cmd = cmd_copy(cmd, argc, argv);
cmd_list_append(new_cmdlist, new_cmd);
}
s = cmd_list_print(new_cmdlist, 0);
log_debug("%s: %s", __func__, s);
free(s);
return (new_cmdlist);
}
/* Get a command list as a string. */
char *
cmd_list_print(const struct cmd_list *cmdlist, int escaped)
cmd_list_print(struct cmd_list *cmdlist, int escaped)
{
struct cmd *cmd, *next;
char *buf, *this;
@ -810,14 +763,10 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp,
if ((wl = cmd_mouse_window(m, sp)) == NULL)
return (NULL);
if (m->wp == -1)
wp = wl->window->active;
else {
if ((wp = window_pane_find_by_id(m->wp)) == NULL)
return (NULL);
if (!window_has_pane(wl->window, wp))
return (NULL);
}
if ((wp = window_pane_find_by_id(m->wp)) == NULL)
return (NULL);
if (!window_has_pane(wl->window, wp))
return (NULL);
if (wlp != NULL)
*wlp = wl;

221
colour.c
View File

@ -105,21 +105,6 @@ colour_split_rgb(int c, u_char *r, u_char *g, u_char *b)
*b = c & 0xff;
}
/* Force colour to RGB if not already. */
int
colour_force_rgb(int c)
{
if (c & COLOUR_FLAG_RGB)
return (c);
if (c & COLOUR_FLAG_256)
return (colour_256toRGB(c));
if (c >= 0 && c <= 7)
return (colour_256toRGB(c));
if (c >= 90 && c <= 97)
return (colour_256toRGB(8 + c - 90));
return (-1);
}
/* Convert colour to a string. */
const char *
colour_tostring(int c)
@ -128,7 +113,7 @@ colour_tostring(int c)
u_char r, g, b;
if (c == -1)
return ("none");
return ("invalid");
if (c & COLOUR_FLAG_RGB) {
colour_split_rgb(c, &r, &g, &b);
@ -182,46 +167,6 @@ colour_tostring(int c)
return ("invalid");
}
/* Convert background colour to theme. */
enum client_theme
colour_totheme(int c)
{
int r, g, b, brightness;
if (c == -1)
return (THEME_UNKNOWN);
if (c & COLOUR_FLAG_RGB) {
r = (c >> 16) & 0xff;
g = (c >> 8) & 0xff;
b = (c >> 0) & 0xff;
brightness = r + g + b;
if (brightness > 382)
return (THEME_LIGHT);
return (THEME_DARK);
}
if (c & COLOUR_FLAG_256)
return (colour_totheme(colour_256toRGB(c)));
switch (c) {
case 0:
case 90:
return (THEME_DARK);
case 7:
case 97:
return (THEME_LIGHT);
default:
if (c >= 0 && c <= 7)
return (colour_totheme(colour_256toRGB(c)));
if (c >= 90 && c <= 97)
return (colour_totheme(colour_256toRGB(8 + c - 90)));
break;
}
return (THEME_UNKNOWN);
}
/* Convert colour from string. */
int
colour_fromstring(const char *s)
@ -982,17 +927,13 @@ colour_byname(const char *name)
{ "yellow3", 0xcdcd00 },
{ "yellow4", 0x8b8b00 }
};
u_int i;
int c;
const char *errstr;
u_int i;
int c;
if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) {
if (name[4] == '\0')
if (!isdigit((u_char)name[4]))
return (0xbebebe|COLOUR_FLAG_RGB);
c = strtonum(name + 4, 0, 100, &errstr);
if (errstr != NULL)
return (-1);
c = round(2.55 * c);
c = round(2.55 * atoi(name + 4));
if (c < 0 || c > 255)
return (-1);
return (colour_join_rgb(c, c, c));
@ -1003,155 +944,3 @@ colour_byname(const char *name)
}
return (-1);
}
/* Parse colour from an X11 string. */
int
colour_parseX11(const char *p)
{
double c, m, y, k = 0;
u_int r, g, b;
size_t len = strlen(p);
int colour = -1;
char *copy;
if ((len == 12 && sscanf(p, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) ||
(len == 7 && sscanf(p, "#%02x%02x%02x", &r, &g, &b) == 3) ||
sscanf(p, "%d,%d,%d", &r, &g, &b) == 3)
colour = colour_join_rgb(r, g, b);
else if ((len == 18 &&
sscanf(p, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) ||
(len == 13 && sscanf(p, "#%04x%04x%04x", &r, &g, &b) == 3))
colour = colour_join_rgb(r >> 8, g >> 8, b >> 8);
else if ((sscanf(p, "cmyk:%lf/%lf/%lf/%lf", &c, &m, &y, &k) == 4 ||
sscanf(p, "cmy:%lf/%lf/%lf", &c, &m, &y) == 3) &&
c >= 0 && c <= 1 && m >= 0 && m <= 1 &&
y >= 0 && y <= 1 && k >= 0 && k <= 1) {
colour = colour_join_rgb(
(1 - c) * (1 - k) * 255,
(1 - m) * (1 - k) * 255,
(1 - y) * (1 - k) * 255);
} else {
while (len != 0 && *p == ' ') {
p++;
len--;
}
while (len != 0 && p[len - 1] == ' ')
len--;
copy = xstrndup(p, len);
colour = colour_byname(copy);
free(copy);
}
log_debug("%s: %s = %s", __func__, p, colour_tostring(colour));
return (colour);
}
/* Initialize palette. */
void
colour_palette_init(struct colour_palette *p)
{
p->fg = 8;
p->bg = 8;
p->palette = NULL;
p->default_palette = NULL;
}
/* Clear palette. */
void
colour_palette_clear(struct colour_palette *p)
{
if (p != NULL) {
p->fg = 8;
p->bg = 8;
free(p->palette);
p->palette = NULL;
}
}
/* Free a palette. */
void
colour_palette_free(struct colour_palette *p)
{
if (p != NULL) {
free(p->palette);
p->palette = NULL;
free(p->default_palette);
p->default_palette = NULL;
}
}
/* Get a colour from a palette. */
int
colour_palette_get(struct colour_palette *p, int c)
{
if (p == NULL)
return (-1);
if (c >= 90 && c <= 97)
c = 8 + c - 90;
else if (c & COLOUR_FLAG_256)
c &= ~COLOUR_FLAG_256;
else if (c >= 8)
return (-1);
if (p->palette != NULL && p->palette[c] != -1)
return (p->palette[c]);
if (p->default_palette != NULL && p->default_palette[c] != -1)
return (p->default_palette[c]);
return (-1);
}
/* Set a colour in a palette. */
int
colour_palette_set(struct colour_palette *p, int n, int c)
{
u_int i;
if (p == NULL || n > 255)
return (0);
if (c == -1 && p->palette == NULL)
return (0);
if (c != -1 && p->palette == NULL) {
if (p->palette == NULL)
p->palette = xcalloc(256, sizeof *p->palette);
for (i = 0; i < 256; i++)
p->palette[i] = -1;
}
p->palette[n] = c;
return (1);
}
/* Build palette defaults from an option. */
void
colour_palette_from_option(struct colour_palette *p, struct options *oo)
{
struct options_entry *o;
struct options_array_item *a;
u_int i, n;
int c;
if (p == NULL)
return;
o = options_get(oo, "pane-colours");
if ((a = options_array_first(o)) == NULL) {
if (p->default_palette != NULL) {
free(p->default_palette);
p->default_palette = NULL;
}
return;
}
if (p->default_palette == NULL)
p->default_palette = xcalloc(256, sizeof *p->default_palette);
for (i = 0; i < 256; i++)
p->default_palette[i] = -1;
while (a != NULL) {
n = options_array_item_index(a);
if (n < 256) {
c = options_array_item_value(a)->number;
p->default_palette[n] = c;
}
a = options_array_next(a);
}
}

View File

@ -38,14 +38,6 @@
#include <event2/bufferevent_compat.h>
#else
#include <event.h>
#ifndef EVBUFFER_EOL_LF
/*
* This doesn't really work because evbuffer_readline is broken, but gets us to
* build with very old (older than 1.4.14) libevent.
*/
#define EVBUFFER_EOL_LF
#define evbuffer_readln(a, b, c) evbuffer_readline(a)
#endif
#endif
#ifdef HAVE_MALLOC_TRIM
@ -297,11 +289,6 @@ void explicit_bzero(void *, size_t);
int getdtablecount(void);
#endif
#ifndef HAVE_GETDTABLESIZE
/* getdtablesize.c */
int getdtablesize(void);
#endif
#ifndef HAVE_CLOSEFROM
/* closefrom.c */
void closefrom(int);
@ -347,23 +334,6 @@ char *strndup(const char *, size_t);
void *memmem(const void *, size_t, const void *, size_t);
#endif
#ifndef HAVE_HTONLL
/* htonll.c */
#undef htonll
uint64_t htonll(uint64_t);
#endif
#ifndef HAVE_NTOHLL
/* ntohll.c */
#undef ntohll
uint64_t ntohll(uint64_t);
#endif
#ifndef HAVE_GETPEEREID
/* getpeereid.c */
int getpeereid(int, uid_t *, gid_t *);
#endif
#ifndef HAVE_DAEMON
/* daemon.c */
int daemon(int, int);
@ -446,13 +416,6 @@ void *reallocarray(void *, size_t, size_t);
void *recallocarray(void *, size_t, size_t, size_t);
#endif
#ifdef HAVE_SYSTEMD
/* systemd.c */
int systemd_activated(void);
int systemd_create_socket(int, char **);
int systemd_move_to_new_cgroup(char **);
#endif
#ifdef HAVE_UTF8PROC
/* utf8proc.c */
int utf8proc_wcwidth(wchar_t);
@ -466,11 +429,11 @@ int utf8proc_wctomb(char *, wchar_t);
#endif
/* getopt.c */
extern int BSDopterr;
extern int BSDoptind;
extern int BSDoptopt;
extern int BSDoptreset;
extern char *BSDoptarg;
extern int BSDopterr;
extern int BSDoptind;
extern int BSDoptopt;
extern int BSDoptreset;
extern char *BSDoptarg;
int BSDgetopt(int, char *const *, const char *);
#define getopt(ac, av, o) BSDgetopt(ac, av, o)
#define opterr BSDopterr

View File

@ -27,7 +27,7 @@
#endif
int
clock_gettime(__unused int clock, struct timespec *ts)
clock_gettime(int clock, struct timespec *ts)
{
struct timeval tv;

115
compat/getopt.c Normal file
View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
#include "compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int BSDopterr = 1, /* if error message should be printed */
BSDoptind = 1, /* index into parent argv vector */
BSDoptopt, /* character checked for validity */
BSDoptreset; /* reset getopt */
char *BSDoptarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
BSDgetopt(int nargc, char *const *nargv, const char *ostr)
{
static const char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (ostr == NULL)
return (-1);
if (BSDoptreset || !*place) { /* update scanning pointer */
BSDoptreset = 0;
if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
if (place[1])
return (BADCH);
++BSDoptind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((BSDoptopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, BSDoptopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (BSDoptopt == (int)'-')
return (-1);
if (!*place)
++BSDoptind;
if (BSDopterr && *ostr != ':')
(void)fprintf(stderr,
"%s: unknown option -- %c\n", getprogname(),
BSDoptopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
BSDoptarg = NULL;
if (!*place)
++BSDoptind;
}
else { /* need an argument */
if (*place) /* no white space */
BSDoptarg = (char *)place;
else if (nargc <= ++BSDoptind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (BSDopterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
getprogname(), BSDoptopt);
return (BADCH);
}
else /* white space */
BSDoptarg = nargv[BSDoptind];
place = EMSG;
++BSDoptind;
}
return (BSDoptopt); /* dump back option letter */
}

View File

@ -1,577 +0,0 @@
/* This file is obtained from OpenSSH:
* Repository: https://github.com/openssh/openssh-portable
* Commit: b5b405fee7f3e79d44e2d2971a4b6b4cc53f112e
* File: /openbsd-compat/getopt_long.c */
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF 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.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE 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.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt_long.c */
#include "compat.h"
/* The following macro constants are taken from getopt.h of OpenSSH:
* Repository: https://github.com/openssh/openssh-portable
* Commit: b5b405fee7f3e79d44e2d2971a4b6b4cc53f112e
* File: /openbsd-compat/getopt.h
*
* ---- BEGIN - Copyright notice and license of getopt.h ----
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE 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.
* ---- END ----
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2
#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET)
#if 0
#include <err.h>
#include <getopt.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG (char *)""
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
}
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, match;
current_argv = place;
match = -1;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
match = i;
else {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*/
if (posixly_correct == -1 || optreset)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#if 0
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
}
#endif
#endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */

View File

@ -1,57 +0,0 @@
/*
* Copyright (c) 2022 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#ifdef HAVE_UCRED_H
#include <ucred.h>
#endif
#include "compat.h"
int
getpeereid(int s, uid_t *uid, gid_t *gid)
{
#ifdef HAVE_SO_PEERCRED
struct ucred uc;
int len = sizeof uc;
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &len) == -1)
return (-1);
*uid = uc.uid;
*gid = uc.gid;
return (0);
#elif defined(HAVE_GETPEERUCRED)
ucred_t *ucred = NULL;
if (getpeerucred(s, &ucred) == -1)
return (-1);
if ((*uid = ucred_geteuid(ucred)) == -1)
return (-1);
if ((*gid = ucred_getrgid(ucred)) == -1)
return (-1);
ucred_free(ucred);
return (0);
#else
*uid = geteuid();
*gid = getegid();
return (0);
#endif
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2024 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
* 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 <arpa/inet.h>
#include <sys/types.h>
#include "compat.h"
uint64_t
htonll(uint64_t v)
{
uint32_t b;
uint32_t t;
b = htonl (v & 0xffffffff);
t = htonl (v >> 32);
return ((uint64_t)b << 32 | t);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
/* $OpenBSD: imsg.c,v 1.37 2024/11/26 13:57:31 claudio Exp $ */
/* $OpenBSD: imsg.c,v 1.16 2017/12/14 09:27:44 kettenis Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@ -22,7 +21,6 @@
#include <sys/uio.h>
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -30,288 +28,203 @@
#include "compat.h"
#include "imsg.h"
#define IMSG_ALLOW_FDPASS 0x01
#define IMSG_FD_MARK 0x80000000U
int imsg_fd_overhead = 0;
static struct ibuf *imsg_parse_hdr(struct ibuf *, void *, int *);
int
imsgbuf_init(struct imsgbuf *imsgbuf, int fd)
{
imsgbuf->w = msgbuf_new_reader(IMSG_HEADER_SIZE, imsg_parse_hdr,
imsgbuf);
if (imsgbuf->w == NULL)
return (-1);
imsgbuf->pid = getpid();
imsgbuf->maxsize = MAX_IMSGSIZE;
imsgbuf->fd = fd;
imsgbuf->flags = 0;
return (0);
}
static int imsg_get_fd(struct imsgbuf *);
void
imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf)
imsg_init(struct imsgbuf *ibuf, int fd)
{
imsgbuf->flags |= IMSG_ALLOW_FDPASS;
}
int
imsgbuf_set_maxsize(struct imsgbuf *imsgbuf, uint32_t maxsize)
{
if (maxsize < IMSG_HEADER_SIZE || maxsize & IMSG_FD_MARK) {
errno = EINVAL;
return (-1);
}
imsgbuf->maxsize = maxsize;
return (0);
}
int
imsgbuf_read(struct imsgbuf *imsgbuf)
{
if (imsgbuf->flags & IMSG_ALLOW_FDPASS)
return msgbuf_read(imsgbuf->fd, imsgbuf->w);
else
return ibuf_read(imsgbuf->fd, imsgbuf->w);
}
int
imsgbuf_write(struct imsgbuf *imsgbuf)
{
if (imsgbuf->flags & IMSG_ALLOW_FDPASS)
return msgbuf_write(imsgbuf->fd, imsgbuf->w);
else
return ibuf_write(imsgbuf->fd, imsgbuf->w);
}
int
imsgbuf_flush(struct imsgbuf *imsgbuf)
{
while (imsgbuf_queuelen(imsgbuf) > 0) {
if (imsgbuf_write(imsgbuf) == -1)
return (-1);
}
return (0);
}
void
imsgbuf_clear(struct imsgbuf *imsgbuf)
{
msgbuf_free(imsgbuf->w);
imsgbuf->w = NULL;
}
uint32_t
imsgbuf_queuelen(struct imsgbuf *imsgbuf)
{
return msgbuf_queuelen(imsgbuf->w);
msgbuf_init(&ibuf->w);
memset(&ibuf->r, 0, sizeof(ibuf->r));
ibuf->fd = fd;
ibuf->w.fd = fd;
ibuf->pid = getpid();
TAILQ_INIT(&ibuf->fds);
}
ssize_t
imsg_get(struct imsgbuf *imsgbuf, struct imsg *imsg)
imsg_read(struct imsgbuf *ibuf)
{
struct imsg m;
struct ibuf *buf;
struct msghdr msg;
struct cmsghdr *cmsg;
union {
struct cmsghdr hdr;
char buf[CMSG_SPACE(sizeof(int) * 1)];
} cmsgbuf;
struct iovec iov;
ssize_t n = -1;
int fd;
struct imsg_fd *ifd;
if ((buf = msgbuf_get(imsgbuf->w)) == NULL)
memset(&msg, 0, sizeof(msg));
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf);
if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
return (-1);
again:
if (getdtablecount() + imsg_fd_overhead +
(int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
>= getdtablesize()) {
errno = EAGAIN;
free(ifd);
return (-1);
}
if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
if (errno == EINTR)
goto again;
goto fail;
}
ibuf->r.wpos += n;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
int i;
int j;
/*
* We only accept one file descriptor. Due to C
* padding rules, our control buffer might contain
* more than one fd, and we must close them.
*/
j = ((char *)cmsg + cmsg->cmsg_len -
(char *)CMSG_DATA(cmsg)) / sizeof(int);
for (i = 0; i < j; i++) {
fd = ((int *)CMSG_DATA(cmsg))[i];
if (ifd != NULL) {
ifd->fd = fd;
TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
entry);
ifd = NULL;
} else
close(fd);
}
}
/* we do not handle other ctl data level */
}
fail:
free(ifd);
return (n);
}
ssize_t
imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
{
size_t av, left, datalen;
av = ibuf->r.wpos;
if (IMSG_HEADER_SIZE > av)
return (0);
if (ibuf_get(buf, &m.hdr, sizeof(m.hdr)) == -1)
memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
if (imsg->hdr.len < IMSG_HEADER_SIZE ||
imsg->hdr.len > MAX_IMSGSIZE) {
errno = ERANGE;
return (-1);
}
if (imsg->hdr.len > av)
return (0);
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
if (datalen == 0)
imsg->data = NULL;
else if ((imsg->data = malloc(datalen)) == NULL)
return (-1);
if (ibuf_size(buf))
m.data = ibuf_data(buf);
if (imsg->hdr.flags & IMSGF_HASFD)
imsg->fd = imsg_get_fd(ibuf);
else
m.data = NULL;
m.buf = buf;
m.hdr.len &= ~IMSG_FD_MARK;
imsg->fd = -1;
*imsg = m;
return (ibuf_size(buf) + IMSG_HEADER_SIZE);
memcpy(imsg->data, ibuf->r.rptr, datalen);
if (imsg->hdr.len < av) {
left = av - imsg->hdr.len;
memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
ibuf->r.wpos = left;
} else
ibuf->r.wpos = 0;
return (datalen + IMSG_HEADER_SIZE);
}
int
imsg_get_ibuf(struct imsg *imsg, struct ibuf *ibuf)
{
if (ibuf_size(imsg->buf) == 0) {
errno = EBADMSG;
return (-1);
}
return ibuf_get_ibuf(imsg->buf, ibuf_size(imsg->buf), ibuf);
}
int
imsg_get_data(struct imsg *imsg, void *data, size_t len)
{
if (len == 0) {
errno = EINVAL;
return (-1);
}
if (ibuf_size(imsg->buf) != len) {
errno = EBADMSG;
return (-1);
}
return ibuf_get(imsg->buf, data, len);
}
int
imsg_get_fd(struct imsg *imsg)
{
return ibuf_fd_get(imsg->buf);
}
uint32_t
imsg_get_id(struct imsg *imsg)
{
return (imsg->hdr.peerid);
}
size_t
imsg_get_len(struct imsg *imsg)
{
return ibuf_size(imsg->buf);
}
pid_t
imsg_get_pid(struct imsg *imsg)
{
return (imsg->hdr.pid);
}
uint32_t
imsg_get_type(struct imsg *imsg)
{
return (imsg->hdr.type);
}
int
imsg_compose(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
int fd, const void *data, size_t datalen)
imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
int fd, const void *data, uint16_t datalen)
{
struct ibuf *wbuf;
if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
return (-1);
if (imsg_add(wbuf, data, datalen) == -1)
return (-1);
ibuf_fd_set(wbuf, fd);
imsg_close(imsgbuf, wbuf);
wbuf->fd = fd;
imsg_close(ibuf, wbuf);
return (1);
}
int
imsg_composev(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
int fd, const struct iovec *iov, int iovcnt)
{
struct ibuf *wbuf;
int i;
size_t datalen = 0;
int i, datalen = 0;
for (i = 0; i < iovcnt; i++)
datalen += iov[i].iov_len;
if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
return (-1);
for (i = 0; i < iovcnt; i++)
if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
return (-1);
ibuf_fd_set(wbuf, fd);
imsg_close(imsgbuf, wbuf);
wbuf->fd = fd;
imsg_close(ibuf, wbuf);
return (1);
}
/*
* Enqueue imsg with payload from ibuf buf. fd passing is not possible
* with this function.
*/
int
imsg_compose_ibuf(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id,
pid_t pid, struct ibuf *buf)
{
struct ibuf *hdrbuf = NULL;
struct imsg_hdr hdr;
int save_errno;
if (ibuf_size(buf) + IMSG_HEADER_SIZE > imsgbuf->maxsize) {
errno = ERANGE;
goto fail;
}
hdr.type = type;
hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
hdr.peerid = id;
if ((hdr.pid = pid) == 0)
hdr.pid = imsgbuf->pid;
if ((hdrbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
goto fail;
if (imsg_add(hdrbuf, &hdr, sizeof(hdr)) == -1)
goto fail;
ibuf_close(imsgbuf->w, hdrbuf);
ibuf_close(imsgbuf->w, buf);
return (1);
fail:
save_errno = errno;
ibuf_free(buf);
ibuf_free(hdrbuf);
errno = save_errno;
return (-1);
}
/*
* Forward imsg to another channel. Any attached fd is closed.
*/
int
imsg_forward(struct imsgbuf *imsgbuf, struct imsg *msg)
{
struct ibuf *wbuf;
size_t len;
ibuf_rewind(msg->buf);
ibuf_skip(msg->buf, sizeof(msg->hdr));
len = ibuf_size(msg->buf);
if ((wbuf = imsg_create(imsgbuf, msg->hdr.type, msg->hdr.peerid,
msg->hdr.pid, len)) == NULL)
return (-1);
if (len != 0) {
if (ibuf_add_ibuf(wbuf, msg->buf) == -1) {
ibuf_free(wbuf);
return (-1);
}
}
imsg_close(imsgbuf, wbuf);
return (1);
}
/* ARGSUSED */
struct ibuf *
imsg_create(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
size_t datalen)
imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
uint16_t datalen)
{
struct ibuf *wbuf;
struct imsg_hdr hdr;
datalen += IMSG_HEADER_SIZE;
if (datalen > imsgbuf->maxsize) {
if (datalen > MAX_IMSGSIZE) {
errno = ERANGE;
return (NULL);
}
hdr.type = type;
hdr.peerid = id;
hdr.flags = 0;
hdr.peerid = peerid;
if ((hdr.pid = pid) == 0)
hdr.pid = imsgbuf->pid;
if ((wbuf = ibuf_dynamic(datalen, imsgbuf->maxsize)) == NULL) {
hdr.pid = ibuf->pid;
if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
return (NULL);
}
if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
@ -321,7 +234,7 @@ imsg_create(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
}
int
imsg_add(struct ibuf *msg, const void *data, size_t datalen)
imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
{
if (datalen)
if (ibuf_add(msg, data, datalen) == -1) {
@ -332,47 +245,58 @@ imsg_add(struct ibuf *msg, const void *data, size_t datalen)
}
void
imsg_close(struct imsgbuf *imsgbuf, struct ibuf *msg)
imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
{
struct imsg_hdr *hdr;
uint32_t len;
len = ibuf_size(msg);
if (ibuf_fd_avail(msg))
len |= IMSG_FD_MARK;
(void)ibuf_set_h32(msg, offsetof(struct imsg_hdr, len), len);
ibuf_close(imsgbuf->w, msg);
hdr = (struct imsg_hdr *)msg->buf;
hdr->flags &= ~IMSGF_HASFD;
if (msg->fd != -1)
hdr->flags |= IMSGF_HASFD;
hdr->len = (uint16_t)msg->wpos;
ibuf_close(&ibuf->w, msg);
}
void
imsg_free(struct imsg *imsg)
{
ibuf_free(imsg->buf);
freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
}
static struct ibuf *
imsg_parse_hdr(struct ibuf *buf, void *arg, int *fd)
static int
imsg_get_fd(struct imsgbuf *ibuf)
{
struct imsgbuf *imsgbuf = arg;
struct imsg_hdr hdr;
struct ibuf *b;
uint32_t len;
int fd;
struct imsg_fd *ifd;
if (ibuf_get(buf, &hdr, sizeof(hdr)) == -1)
return (NULL);
if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
return (-1);
len = hdr.len & ~IMSG_FD_MARK;
fd = ifd->fd;
TAILQ_REMOVE(&ibuf->fds, ifd, entry);
free(ifd);
if (len < IMSG_HEADER_SIZE || len > imsgbuf->maxsize) {
errno = ERANGE;
return (NULL);
}
if ((b = ibuf_open(len)) == NULL)
return (NULL);
if (hdr.len & IMSG_FD_MARK) {
ibuf_fd_set(b, *fd);
*fd = -1;
}
return b;
return (fd);
}
int
imsg_flush(struct imsgbuf *ibuf)
{
while (ibuf->w.queued)
if (msgbuf_write(&ibuf->w) <= 0)
return (-1);
return (0);
}
void
imsg_clear(struct imsgbuf *ibuf)
{
int fd;
msgbuf_clear(&ibuf->w);
while ((fd = imsg_get_fd(ibuf)) != -1)
close(fd);
}

View File

@ -1,7 +1,6 @@
/* $OpenBSD: imsg.h,v 1.19 2024/11/26 13:57:31 claudio Exp $ */
/* $OpenBSD: imsg.h,v 1.5 2019/01/20 02:50:03 bcook Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
* Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -22,7 +21,7 @@
#ifndef _IMSG_H_
#define _IMSG_H_
#include <sys/types.h>
#include <stdint.h>
#define IBUF_READ_SIZE 65535
#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
@ -38,116 +37,77 @@ struct ibuf {
int fd;
};
struct msgbuf;
struct msgbuf {
TAILQ_HEAD(, ibuf) bufs;
uint32_t queued;
int fd;
};
struct ibuf_read {
unsigned char buf[IBUF_READ_SIZE];
unsigned char *rptr;
size_t wpos;
};
struct imsg_fd {
TAILQ_ENTRY(imsg_fd) entry;
int fd;
};
struct imsgbuf {
struct msgbuf *w;
pid_t pid;
uint32_t maxsize;
TAILQ_HEAD(, imsg_fd) fds;
struct ibuf_read r;
struct msgbuf w;
int fd;
int flags;
pid_t pid;
};
#define IMSGF_HASFD 1
struct imsg_hdr {
uint32_t type;
uint32_t len;
uint16_t len;
uint16_t flags;
uint32_t peerid;
uint32_t pid;
};
struct imsg {
struct imsg_hdr hdr;
int fd;
void *data;
struct ibuf *buf;
};
struct iovec;
/* imsg-buffer.c */
/* buffer.c */
struct ibuf *ibuf_open(size_t);
struct ibuf *ibuf_dynamic(size_t, size_t);
int ibuf_add(struct ibuf *, const void *, size_t);
int ibuf_add_ibuf(struct ibuf *, const struct ibuf *);
int ibuf_add_zero(struct ibuf *, size_t);
int ibuf_add_n8(struct ibuf *, uint64_t);
int ibuf_add_n16(struct ibuf *, uint64_t);
int ibuf_add_n32(struct ibuf *, uint64_t);
int ibuf_add_n64(struct ibuf *, uint64_t);
int ibuf_add_h16(struct ibuf *, uint64_t);
int ibuf_add_h32(struct ibuf *, uint64_t);
int ibuf_add_h64(struct ibuf *, uint64_t);
void *ibuf_reserve(struct ibuf *, size_t);
void *ibuf_seek(struct ibuf *, size_t, size_t);
int ibuf_set(struct ibuf *, size_t, const void *, size_t);
int ibuf_set_n8(struct ibuf *, size_t, uint64_t);
int ibuf_set_n16(struct ibuf *, size_t, uint64_t);
int ibuf_set_n32(struct ibuf *, size_t, uint64_t);
int ibuf_set_n64(struct ibuf *, size_t, uint64_t);
int ibuf_set_h16(struct ibuf *, size_t, uint64_t);
int ibuf_set_h32(struct ibuf *, size_t, uint64_t);
int ibuf_set_h64(struct ibuf *, size_t, uint64_t);
void *ibuf_data(const struct ibuf *);
size_t ibuf_size(const struct ibuf *);
size_t ibuf_left(const struct ibuf *);
int ibuf_truncate(struct ibuf *, size_t);
void ibuf_rewind(struct ibuf *);
size_t ibuf_size(struct ibuf *);
size_t ibuf_left(struct ibuf *);
void ibuf_close(struct msgbuf *, struct ibuf *);
void ibuf_from_buffer(struct ibuf *, void *, size_t);
void ibuf_from_ibuf(struct ibuf *, const struct ibuf *);
int ibuf_get(struct ibuf *, void *, size_t);
int ibuf_get_ibuf(struct ibuf *, size_t, struct ibuf *);
int ibuf_get_n8(struct ibuf *, uint8_t *);
int ibuf_get_n16(struct ibuf *, uint16_t *);
int ibuf_get_n32(struct ibuf *, uint32_t *);
int ibuf_get_n64(struct ibuf *, uint64_t *);
int ibuf_get_h16(struct ibuf *, uint16_t *);
int ibuf_get_h32(struct ibuf *, uint32_t *);
int ibuf_get_h64(struct ibuf *, uint64_t *);
char *ibuf_get_string(struct ibuf *, size_t);
int ibuf_skip(struct ibuf *, size_t);
int ibuf_write(struct msgbuf *);
void ibuf_free(struct ibuf *);
int ibuf_fd_avail(struct ibuf *);
int ibuf_fd_get(struct ibuf *);
void ibuf_fd_set(struct ibuf *, int);
struct msgbuf *msgbuf_new(void);
struct msgbuf *msgbuf_new_reader(size_t,
struct ibuf *(*)(struct ibuf *, void *, int *), void *);
void msgbuf_free(struct msgbuf *);
void msgbuf_init(struct msgbuf *);
void msgbuf_clear(struct msgbuf *);
uint32_t msgbuf_queuelen(struct msgbuf *);
int ibuf_write(int, struct msgbuf *);
int msgbuf_write(int, struct msgbuf *);
int ibuf_read(int, struct msgbuf *);
int msgbuf_read(int, struct msgbuf *);
struct ibuf *msgbuf_get(struct msgbuf *);
int msgbuf_write(struct msgbuf *);
void msgbuf_drain(struct msgbuf *, size_t);
/* imsg.c */
int imsgbuf_init(struct imsgbuf *, int);
void imsgbuf_allow_fdpass(struct imsgbuf *imsgbuf);
int imsgbuf_set_maxsize(struct imsgbuf *, uint32_t);
int imsgbuf_read(struct imsgbuf *);
int imsgbuf_write(struct imsgbuf *);
int imsgbuf_flush(struct imsgbuf *);
void imsgbuf_clear(struct imsgbuf *);
uint32_t imsgbuf_queuelen(struct imsgbuf *);
void imsg_init(struct imsgbuf *, int);
ssize_t imsg_read(struct imsgbuf *);
ssize_t imsg_get(struct imsgbuf *, struct imsg *);
int imsg_get_ibuf(struct imsg *, struct ibuf *);
int imsg_get_data(struct imsg *, void *, size_t);
int imsg_get_fd(struct imsg *);
uint32_t imsg_get_id(struct imsg *);
size_t imsg_get_len(struct imsg *);
pid_t imsg_get_pid(struct imsg *);
uint32_t imsg_get_type(struct imsg *);
int imsg_forward(struct imsgbuf *, struct imsg *);
int imsg_compose(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
const void *, size_t);
const void *, uint16_t);
int imsg_composev(struct imsgbuf *, uint32_t, uint32_t, pid_t, int,
const struct iovec *, int);
int imsg_compose_ibuf(struct imsgbuf *, uint32_t, uint32_t, pid_t,
struct ibuf *);
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, size_t);
int imsg_add(struct ibuf *, const void *, size_t);
struct ibuf *imsg_create(struct imsgbuf *, uint32_t, uint32_t, pid_t, uint16_t);
int imsg_add(struct ibuf *, const void *, uint16_t);
void imsg_close(struct imsgbuf *, struct ibuf *);
void imsg_free(struct imsg *);
int imsg_flush(struct imsgbuf *);
void imsg_clear(struct imsgbuf *);
#endif

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 2024 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
* 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 <arpa/inet.h>
#include <sys/types.h>
#include "compat.h"
uint64_t
ntohll(uint64_t v)
{
uint32_t b;
uint32_t t;
b = ntohl (v & 0xffffffff);
t = ntohl (v >> 32);
return ((uint64_t)b << 32 | t);
}

View File

@ -32,8 +32,8 @@
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _COMPAT_QUEUE_H_
#define _COMPAT_QUEUE_H_
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
@ -530,4 +530,4 @@ struct { \
} \
} while (0)
#endif /* !_COMPAT_QUEUE_H_ */
#endif /* !_SYS_QUEUE_H_ */

View File

@ -17,7 +17,6 @@
#include <sys/types.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "compat.h"

View File

@ -1,326 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2022 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/un.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-daemon.h>
#include <systemd/sd-login.h>
#include <systemd/sd-id128.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
#ifndef SD_ID128_UUID_FORMAT_STR
#define SD_ID128_UUID_FORMAT_STR \
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
#endif
int
systemd_activated(void)
{
return (sd_listen_fds(0) >= 1);
}
int
systemd_create_socket(int flags, char **cause)
{
int fds;
int fd;
struct sockaddr_un sa;
socklen_t addrlen = sizeof sa;
fds = sd_listen_fds(0);
if (fds > 1) { /* too many file descriptors */
errno = E2BIG;
goto fail;
}
if (fds == 1) { /* socket-activated */
fd = SD_LISTEN_FDS_START;
if (!sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0)) {
errno = EPFNOSUPPORT;
goto fail;
}
if (getsockname(fd, (struct sockaddr *)&sa, &addrlen) == -1)
goto fail;
socket_path = xstrdup(sa.sun_path);
return (fd);
}
return (server_create_socket(flags, cause));
fail:
if (cause != NULL)
xasprintf(cause, "systemd socket error (%s)", strerror(errno));
return (-1);
}
struct systemd_job_watch {
const char *path;
int done;
};
static int
job_removed_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
struct systemd_job_watch *watch = userdata;
const char *path = NULL;
uint32_t id;
int r;
/* This handler could be called during the sd_bus_call. */
if (watch->path == NULL)
return 0;
r = sd_bus_message_read(m, "uo", &id, &path);
if (r < 0)
return (r);
if (strcmp(path, watch->path) == 0)
watch->done = 1;
return (0);
}
int
systemd_move_to_new_cgroup(char **cause)
{
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message *m = NULL, *reply = NULL;
sd_bus *bus = NULL;
sd_bus_slot *slot = NULL;
char *name, *desc, *slice;
sd_id128_t uuid;
int r;
uint64_t elapsed_usec;
pid_t pid, parent_pid;
struct timeval start, now;
struct systemd_job_watch watch = {};
gettimeofday(&start, NULL);
/* Connect to the session bus. */
r = sd_bus_default_user(&bus);
if (r < 0) {
xasprintf(cause, "failed to connect to session bus: %s",
strerror(-r));
goto finish;
}
/* Start watching for JobRemoved events */
r = sd_bus_match_signal(bus, &slot,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"JobRemoved",
job_removed_handler,
&watch);
if (r < 0) {
xasprintf(cause, "failed to create match signal: %s",
strerror(-r));
goto finish;
}
/* Start building the method call. */
r = sd_bus_message_new_method_call(bus, &m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartTransientUnit");
if (r < 0) {
xasprintf(cause, "failed to create bus message: %s",
strerror(-r));
goto finish;
}
/* Generate a unique name for the new scope, to avoid collisions. */
r = sd_id128_randomize(&uuid);
if (r < 0) {
xasprintf(cause, "failed to generate uuid: %s", strerror(-r));
goto finish;
}
xasprintf(&name, "tmux-spawn-" SD_ID128_UUID_FORMAT_STR ".scope",
SD_ID128_FORMAT_VAL(uuid));
r = sd_bus_message_append(m, "s", name);
free(name);
if (r < 0) {
xasprintf(cause, "failed to append to bus message: %s",
strerror(-r));
goto finish;
}
/* Mode: fail if there's a queued unit with the same name. */
r = sd_bus_message_append(m, "s", "fail");
if (r < 0) {
xasprintf(cause, "failed to append to bus message: %s",
strerror(-r));
goto finish;
}
/* Start properties array. */
r = sd_bus_message_open_container(m, 'a', "(sv)");
if (r < 0) {
xasprintf(cause, "failed to start properties array: %s",
strerror(-r));
goto finish;
}
pid = getpid();
parent_pid = getppid();
xasprintf(&desc, "tmux child pane %ld launched by process %ld",
(long)pid, (long)parent_pid);
r = sd_bus_message_append(m, "(sv)", "Description", "s", desc);
free(desc);
if (r < 0) {
xasprintf(cause, "failed to append to properties: %s",
strerror(-r));
goto finish;
}
/*
* Make sure that the session shells are terminated with SIGHUP since
* bash and friends tend to ignore SIGTERM.
*/
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", 1);
if (r < 0) {
xasprintf(cause, "failed to append to properties: %s",
strerror(-r));
goto finish;
}
/*
* Inherit the slice from the parent process, or default to
* "app-tmux.slice" if that fails.
*/
r = sd_pid_get_user_slice(parent_pid, &slice);
if (r < 0) {
slice = xstrdup("app-tmux.slice");
}
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
free(slice);
if (r < 0) {
xasprintf(cause, "failed to append to properties: %s",
strerror(-r));
goto finish;
}
/* PIDs to add to the scope: length - 1 array of uint32_t. */
r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
if (r < 0) {
xasprintf(cause, "failed to append to properties: %s",
strerror(-r));
goto finish;
}
/* Clean up the scope even if it fails. */
r = sd_bus_message_append(m, "(sv)", "CollectMode", "s",
"inactive-or-failed");
if (r < 0) {
xasprintf(cause, "failed to append to properties: %s",
strerror(-r));
goto finish;
}
/* End properties array. */
r = sd_bus_message_close_container(m);
if (r < 0) {
xasprintf(cause, "failed to end properties array: %s",
strerror(-r));
goto finish;
}
/* aux is currently unused and should be passed an empty array. */
r = sd_bus_message_append(m, "a(sa(sv))", 0);
if (r < 0) {
xasprintf(cause, "failed to append to bus message: %s",
strerror(-r));
goto finish;
}
/* Call the method with a timeout of 1 second = 1e6 us. */
r = sd_bus_call(bus, m, 1000000, &error, &reply);
if (r < 0) {
if (error.message != NULL) {
/* We have a specific error message from sd-bus. */
xasprintf(cause, "StartTransientUnit call failed: %s",
error.message);
} else {
xasprintf(cause, "StartTransientUnit call failed: %s",
strerror(-r));
}
goto finish;
}
/* Get the job (object path) from the reply */
r = sd_bus_message_read(reply, "o", &watch.path);
if (r < 0) {
xasprintf(cause, "failed to parse method reply: %s",
strerror(-r));
goto finish;
}
while (!watch.done) {
/* Process events including callbacks. */
r = sd_bus_process(bus, NULL);
if (r < 0) {
xasprintf(cause,
"failed waiting for cgroup allocation: %s",
strerror(-r));
goto finish;
}
/*
* A positive return means we handled an event and should keep
* processing; zero indicates no events available, so wait.
*/
if (r > 0)
continue;
gettimeofday(&now, NULL);
elapsed_usec = (now.tv_sec - start.tv_sec) * 1000000 +
now.tv_usec - start.tv_usec;
if (elapsed_usec >= 1000000) {
xasprintf(cause,
"timeout waiting for cgroup allocation");
goto finish;
}
r = sd_bus_wait(bus, 1000000 - elapsed_usec);
if (r < 0) {
xasprintf(cause,
"failed waiting for cgroup allocation: %s",
strerror(-r));
goto finish;
}
}
finish:
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_message_unref(reply);
sd_bus_slot_unref(slot);
sd_bus_unref(bus);
return (r);
}

View File

@ -1,6 +1,6 @@
# configure.ac
AC_INIT([tmux], next-3.6)
AC_INIT([tmux], 3.2)
AC_PREREQ([2.60])
AC_CONFIG_AUX_DIR(etc)
@ -24,27 +24,27 @@ SAVED_LDFLAGS="$LDFLAGS"
# Is this oss-fuzz build?
AC_ARG_ENABLE(
fuzzing,
AS_HELP_STRING(--enable-fuzzing, build fuzzers)
AC_HELP_STRING(--enable-fuzzing, build fuzzers)
)
AC_ARG_VAR(
FUZZING_LIBS,
AS_HELP_STRING(libraries to link fuzzing targets with)
AC_HELP_STRING(libraries to link fuzzing targets with)
)
# Set up convenient fuzzing defaults before initializing compiler.
if test "x$enable_fuzzing" = xyes; then
AC_DEFINE(NEED_FUZZING)
test "x$CC" = x && CC=clang
test "x$FUZZING_LIBS" = x && \
test "x$CC" == x && CC=clang
test "x$FUZZING_LIBS" == x && \
FUZZING_LIBS="-fsanitize=fuzzer"
test "x$SAVED_CFLAGS" = x && \
test "x$SAVED_CFLAGS" == x && \
AM_CFLAGS="-g -fsanitize=fuzzer-no-link,address"
fi
# Set up the compiler in two different ways and say yes we may want to install.
AC_PROG_CC
AM_PROG_CC_C_O
m4_version_prereq(2.70, [AC_PROG_CC], [AC_PROG_CC_C99])
AC_PROG_CC_C99
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
@ -56,45 +56,24 @@ AC_USE_SYSTEM_EXTENSIONS
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
# Is this --enable-debug?
case "x$VERSION" in xnext*) enable_debug=yes;; esac
AC_ARG_ENABLE(
debug,
AS_HELP_STRING(--enable-debug, enable debug build flags),
,
[case "x$VERSION" in xnext*) enable_debug=yes;; esac]
AC_HELP_STRING(--enable-debug, enable debug build flags),
)
AM_CONDITIONAL(IS_DEBUG, test "x$enable_debug" = xyes)
# Is this a static build?
AC_ARG_ENABLE(
static,
AS_HELP_STRING(--enable-static, create a static build)
AC_HELP_STRING(--enable-static, create a static build)
)
if test "x$enable_static" = xyes; then
case "$host_os" in
*darwin*)
AC_MSG_ERROR([static linking is not supported on macOS])
;;
esac
test "x$PKG_CONFIG" != x && PKG_CONFIG="$PKG_CONFIG --static"
AM_LDFLAGS="-static $AM_LDFLAGS"
LDFLAGS="$AM_LDFLAGS $SAVED_LDFLAGS"
fi
# Allow default TERM to be set.
AC_ARG_WITH(
TERM,
AS_HELP_STRING(--with-TERM, set default TERM),
[DEFAULT_TERM=$withval],
[DEFAULT_TERM=]
)
case "x$DEFAULT_TERM" in
xscreen*|xtmux*|x)
;;
*)
AC_MSG_ERROR("unsuitable TERM (must be screen* or tmux*)")
;;
esac
# Do we need fuzzers?
AM_CONDITIONAL(NEED_FUZZING, test "x$enable_fuzzing" = xyes)
@ -129,7 +108,6 @@ AC_CHECK_HEADERS([ \
sys/dir.h \
sys/ndir.h \
sys/tree.h \
ucred.h \
util.h \
])
@ -148,7 +126,6 @@ AC_CHECK_FUNCS([ \
flock \
prctl \
proc_pidinfo \
getpeerucred \
sysconf
])
@ -163,12 +140,9 @@ AC_REPLACE_FUNCS([ \
freezero \
getdtablecount \
getdtablesize \
getpeereid \
getline \
getprogname \
htonll \
memmem \
ntohll \
setenv \
setproctitle \
strcasestr \
@ -176,20 +150,10 @@ AC_REPLACE_FUNCS([ \
strlcpy \
strndup \
strsep \
strtonum \
])
AC_FUNC_STRNLEN
# Check if strtonum works.
AC_MSG_CHECKING([for working strtonum])
AC_RUN_IFELSE([AC_LANG_PROGRAM(
[#include <stdlib.h>],
[return (strtonum("0", 0, 1, NULL) == 0 ? 0 : 1);]
)],
[AC_DEFINE(HAVE_STRTONUM) AC_MSG_RESULT(yes)],
[AC_LIBOBJ(strtonum) AC_MSG_RESULT(no)],
[AC_LIBOBJ(strtonum) AC_MSG_RESULT(no)]
)
# Clang sanitizers wrap reallocarray even if it isn't available on the target
# system. When compiled it always returns NULL and crashes the program. To
# detect this we need a more complicated test.
@ -199,7 +163,6 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
[return (reallocarray(NULL, 1, 1) == NULL);]
)],
AC_MSG_RESULT(yes),
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])],
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])]
)
AC_MSG_CHECKING([for working recallocarray])
@ -208,7 +171,6 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
[return (recallocarray(NULL, 1, 1, 1) == NULL);]
)],
AC_MSG_RESULT(yes),
[AC_LIBOBJ(recallocarray) AC_MSG_RESULT([no])],
[AC_LIBOBJ(recallocarray) AC_MSG_RESULT([no])]
)
@ -219,7 +181,7 @@ AC_SEARCH_LIBS(clock_gettime, rt)
# musl does not set optarg to NULL for flags without arguments (although it is
# not required to, but it is helpful) 3) there are probably other weird
# implementations.
AC_LIBOBJ(getopt_long)
AC_LIBOBJ(getopt)
# Look for libevent. Try libevent_core or libevent with pkg-config first then
# look for the library.
@ -270,12 +232,6 @@ if test "x$found_libevent" = xno; then
AC_MSG_ERROR("libevent not found")
fi
# Look for yacc.
AC_CHECK_PROG(found_yacc, $YACC, yes, no)
if test "x$found_yacc" = xno; then
AC_MSG_ERROR("yacc not found")
fi
# Look for ncurses or curses. Try pkg-config first then directly for the
# library.
PKG_CHECK_MODULES(
@ -318,7 +274,7 @@ fi
if test "x$found_ncurses" = xno; then
AC_SEARCH_LIBS(
setupterm,
[tinfo terminfo ncurses ncursesw],
[tinfo ncurses ncursesw],
found_ncurses=yes,
found_ncurses=no
)
@ -331,7 +287,6 @@ if test "x$found_ncurses" = xno; then
fi
fi
if test "x$found_ncurses" = xyes; then
CPPFLAGS="$CPPFLAGS -DHAVE_NCURSES_H"
AC_DEFINE(HAVE_NCURSES_H)
else
AC_CHECK_LIB(
@ -347,21 +302,16 @@ else
)
if test "x$found_curses" = xyes; then
LIBS="$LIBS -lcurses"
CPPFLAGS="$CPPFLAGS -DHAVE_CURSES_H"
AC_DEFINE(HAVE_CURSES_H)
else
AC_MSG_ERROR("curses not found")
fi
fi
AC_CHECK_FUNCS([ \
tiparm \
tiparm_s \
])
# Look for utempter.
AC_ARG_ENABLE(
utempter,
AS_HELP_STRING(--enable-utempter, use utempter if it is installed)
AC_HELP_STRING(--enable-utempter, use utempter if it is installed)
)
if test "x$enable_utempter" = xyes; then
AC_CHECK_HEADER(utempter.h, enable_utempter=yes, enable_utempter=no)
@ -383,18 +333,9 @@ fi
# Look for utf8proc.
AC_ARG_ENABLE(
utf8proc,
AS_HELP_STRING(--enable-utf8proc, use utf8proc if it is installed)
AC_HELP_STRING(--enable-utf8proc, use utf8proc if it is installed)
)
if test "x$enable_utf8proc" = xyes; then
PKG_CHECK_MODULES(
LIBUTF8PROC,
libutf8proc,
[
AM_CPPFLAGS="$LIBUTF8PROC_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$LIBUTF8PROC_CFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBUTF8PROC_LIBS $LIBS"
]
)
AC_CHECK_HEADER(utf8proc.h, enable_utf8proc=yes, enable_utf8proc=no)
if test "x$enable_utf8proc" = xyes; then
AC_SEARCH_LIBS(
@ -412,67 +353,15 @@ if test "x$enable_utf8proc" = xyes; then
fi
AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes])
# Check for systemd support.
AC_ARG_ENABLE(
systemd,
AS_HELP_STRING(--enable-systemd, enable systemd integration)
)
if test x"$enable_systemd" = xyes; then
PKG_CHECK_MODULES(
SYSTEMD,
libsystemd,
[
AM_CPPFLAGS="$SYSTEMD_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
LIBS="$SYSTEMD_LIBS $LIBS"
found_systemd=yes
],
found_systemd=no
)
if test "x$found_systemd" = xyes; then
AC_DEFINE(HAVE_SYSTEMD)
else
AC_MSG_ERROR("systemd not found")
fi
fi
AM_CONDITIONAL(HAVE_SYSTEMD, [test "x$found_systemd" = xyes])
AC_ARG_ENABLE(
cgroups,
AS_HELP_STRING(--disable-cgroups, disable adding panes to new cgroups with systemd)
)
if test "x$enable_cgroups" = x; then
# Default to the same as $enable_systemd.
enable_cgroups=$enable_systemd
fi
if test "x$enable_cgroups" = xyes; then
if test "x$found_systemd" = xyes; then
AC_DEFINE(ENABLE_CGROUPS)
else
AC_MSG_ERROR("cgroups requires systemd to be enabled")
fi
fi
# Enable sixel support.
AC_ARG_ENABLE(
sixel,
AS_HELP_STRING(--enable-sixel, enable sixel images)
)
if test "x$enable_sixel" = xyes; then
AC_DEFINE(ENABLE_SIXEL)
fi
AM_CONDITIONAL(ENABLE_SIXEL, [test "x$enable_sixel" = xyes])
# Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
AC_MSG_CHECKING(for b64_ntop)
AC_LINK_IFELSE([AC_LANG_PROGRAM(
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[
b64_ntop(NULL, 0, NULL, 0);
])],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
@ -481,15 +370,13 @@ OLD_LIBS="$LIBS"
if test "x$found_b64_ntop" = xno; then
AC_MSG_CHECKING(for b64_ntop with -lresolv)
LIBS="$OLD_LIBS -lresolv"
AC_LINK_IFELSE([AC_LANG_PROGRAM(
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[
b64_ntop(NULL, 0, NULL, 0);
])],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
@ -498,15 +385,13 @@ fi
if test "x$found_b64_ntop" = xno; then
AC_MSG_CHECKING(for b64_ntop with -lnetwork)
LIBS="$OLD_LIBS -lnetwork"
AC_LINK_IFELSE([AC_LANG_PROGRAM(
AC_TRY_LINK(
[
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
],
[
b64_ntop(NULL, 0, NULL, 0);
])],
[b64_ntop(NULL, 0, NULL, 0);],
found_b64_ntop=yes,
found_b64_ntop=no
)
@ -549,24 +434,6 @@ if test "x$found_malloc_trim" = xyes; then
AC_DEFINE(HAVE_MALLOC_TRIM)
fi
# Build against jemalloc if requested.
AC_ARG_ENABLE(
jemalloc,
AS_HELP_STRING(--enable-jemalloc, use jemalloc if it is installed)
)
if test "x$enable_jemalloc" = xyes; then
PKG_CHECK_MODULES(
JEMALLOC,
jemalloc,
[
AM_CPPFLAGS="$JEMALLOC_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBS $JEMALLOC_LIBS"
],
AC_MSG_ERROR("jemalloc not found")
)
fi
# Check for CMSG_DATA. On some platforms like HP-UX this requires UNIX 95
# (_XOPEN_SOURCE and _XOPEN_SOURCE_EXTENDED) (see xopen_networking(7)). On
# others, UNIX 03 (_XOPEN_SOURCE 600, see standards(7) on Solaris).
@ -638,9 +505,9 @@ else
AC_LIBOBJ(err)
fi
# Look for imsg_add in libutil.
AC_SEARCH_LIBS(imsg_add, util, found_imsg_add=yes, found_imsg_add=no)
if test "x$found_imsg_add" = xyes; then
# Look for imsg_init in libutil.
AC_SEARCH_LIBS(imsg_init, util, found_imsg_init=yes, found_imsg_init=no)
if test "x$found_imsg_init" = xyes; then
AC_DEFINE(HAVE_IMSG)
else
AC_LIBOBJ(imsg)
@ -721,7 +588,7 @@ AC_CHECK_DECL(
)
AC_CHECK_DECL(
TAILQ_PREV,
,
found_queue_h=yes,
found_queue_h=no,
[#include <sys/queue.h>]
)
@ -777,14 +644,6 @@ AC_CHECK_DECL(
[#include <sys/prctl.h>]
)
# Look for setsockopt(SO_PEERCRED).
AC_CHECK_DECL(
SO_PEERCRED,
AC_DEFINE(HAVE_SO_PEERCRED),
,
[#include <sys/socket.h>]
)
# Look for fcntl(F_CLOSEM).
AC_CHECK_DECL(
F_CLOSEM,
@ -802,74 +661,6 @@ else
AC_MSG_RESULT(no)
fi
# Try to figure out what the best value for TERM might be.
if test "x$DEFAULT_TERM" = x; then
DEFAULT_TERM=screen
AC_MSG_CHECKING(TERM)
AC_RUN_IFELSE([AC_LANG_SOURCE(
[
#include <stdio.h>
#include <stdlib.h>
#if defined(HAVE_CURSES_H)
#include <curses.h>
#elif defined(HAVE_NCURSES_H)
#include <ncurses.h>
#endif
#include <term.h>
int main(void) {
if (setupterm("screen-256color", -1, NULL) != OK)
exit(1);
exit(0);
}
])],
[DEFAULT_TERM=screen-256color],
,
[DEFAULT_TERM=screen]
)
AC_RUN_IFELSE([AC_LANG_SOURCE(
[
#include <stdio.h>
#include <stdlib.h>
#if defined(HAVE_CURSES_H)
#include <curses.h>
#elif defined(HAVE_NCURSES_H)
#include <ncurses.h>
#endif
#include <term.h>
int main(void) {
if (setupterm("tmux", -1, NULL) != OK)
exit(1);
exit(0);
}
])],
[DEFAULT_TERM=tmux],
,
[DEFAULT_TERM=screen]
)
AC_RUN_IFELSE([AC_LANG_SOURCE(
[
#include <stdio.h>
#include <stdlib.h>
#if defined(HAVE_CURSES_H)
#include <curses.h>
#elif defined(HAVE_NCURSES_H)
#include <ncurses.h>
#endif
#include <term.h>
int main(void) {
if (setupterm("tmux-256color", -1, NULL) != OK)
exit(1);
exit(0);
}
])],
[DEFAULT_TERM=tmux-256color],
,
[DEFAULT_TERM=screen]
)
AC_MSG_RESULT($DEFAULT_TERM)
fi
AC_SUBST(DEFAULT_TERM)
# Man page defaults to mdoc.
MANFORMAT=mdoc
AC_SUBST(MANFORMAT)
@ -885,32 +676,19 @@ case "$host_os" in
AC_MSG_RESULT(darwin)
PLATFORM=darwin
#
# macOS uses __dead2 instead of __dead, like FreeBSD. But it defines
# __dead away so it needs to be removed before we can replace it.
# OS X uses __dead2 instead of __dead, like FreeBSD. But it
# defines __dead away so it needs to be removed before we can
# replace it.
#
AC_DEFINE(BROKEN___DEAD)
#
# macOS CMSG_FIRSTHDR is broken, so redefine it with a working one.
# daemon works but has some stupid side effects, so use our internal
# version which has a workaround.
# OS X CMSG_FIRSTHDR is broken, so redefine it with a working
# one. daemon works but has some stupid side effects, so use
# our internal version which has a workaround.
#
AC_DEFINE(BROKEN_CMSG_FIRSTHDR)
AC_LIBOBJ(daemon)
AC_LIBOBJ(daemon-darwin)
#
# macOS wcwidth(3) is bad, so complain and suggest using utf8proc
# instead.
#
if test "x$enable_utf8proc" = x; then
AC_MSG_NOTICE([])
AC_MSG_NOTICE([ macOS library support for Unicode is very poor,])
AC_MSG_NOTICE([ particularly for complex codepoints like emojis;])
AC_MSG_NOTICE([ to use these correctly, configuring with])
AC_MSG_NOTICE([ --enable-utf8proc is recommended. To build])
AC_MSG_NOTICE([ without anyway, use --disable-utf8proc])
AC_MSG_NOTICE([])
AC_MSG_ERROR([must give --enable-utf8proc or --disable-utf8proc])
fi
;;
*dragonfly*)
AC_MSG_RESULT(dragonfly)
@ -945,13 +723,8 @@ case "$host_os" in
MANFORMAT=mdoc
;;
*)
if test `uname -o 2>/dev/null` = illumos; then
# Illumos uses mandoc.
MANFORMAT=mdoc
else
# Solaris 2.0 to 11.3 use AT&T nroff.
MANFORMAT=man
fi
# Solaris 2.0 to 11.3 use AT&T nroff.
MANFORMAT=man
;;
esac
;;
@ -982,23 +755,9 @@ AM_CONDITIONAL(IS_NETBSD, test "x$PLATFORM" = xnetbsd)
AM_CONDITIONAL(IS_OPENBSD, test "x$PLATFORM" = xopenbsd)
AM_CONDITIONAL(IS_SUNOS, test "x$PLATFORM" = xsunos)
AM_CONDITIONAL(IS_HPUX, test "x$PLATFORM" = xhpux)
AM_CONDITIONAL(IS_CYGWIN, test "x$PLATFORM" = xcygwin)
AM_CONDITIONAL(IS_HAIKU, test "x$PLATFORM" = xhaiku)
AM_CONDITIONAL(IS_UNKNOWN, test "x$PLATFORM" = xunknown)
# Set the default lock command
DEFAULT_LOCK_CMD="lock -np"
AC_MSG_CHECKING(lock-command)
if test "x$PLATFORM" = xlinux; then
AC_CHECK_PROG(found_vlock, vlock, yes, no)
if test "x$found_vlock" = xyes; then
DEFAULT_LOCK_CMD="vlock"
fi
fi
AC_MSG_RESULT($DEFAULT_LOCK_CMD)
AC_SUBST(DEFAULT_LOCK_CMD)
# Save our CFLAGS/CPPFLAGS/LDFLAGS for the Makefile and restore the old user
# variables.
AC_SUBST(AM_CPPFLAGS)
@ -1009,5 +768,4 @@ AC_SUBST(AM_LDFLAGS)
LDFLAGS="$SAVED_LDFLAGS"
# autoconf should create a Makefile.
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
AC_OUTPUT(Makefile)

View File

@ -234,29 +234,3 @@ control_notify_session_window_changed(struct session *s)
s->curw->window->id);
}
}
void
control_notify_paste_buffer_changed(const char *name)
{
struct client *c;
TAILQ_FOREACH(c, &clients, entry) {
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
continue;
control_write(c, "%%paste-buffer-changed %s", name);
}
}
void
control_notify_paste_buffer_deleted(const char *name)
{
struct client *c;
TAILQ_FOREACH(c, &clients, entry) {
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
continue;
control_write(c, "%%paste-buffer-deleted %s", name);
}
}

View File

@ -385,7 +385,7 @@ control_pause_pane(struct client *c, struct window_pane *wp)
}
/* Write a line. */
static void printflike(2, 0)
static void
control_vwrite(struct client *c, const char *fmt, va_list ap)
{
struct control_state *cs = c->control_state;
@ -664,7 +664,7 @@ control_write_pending(struct client *c, struct control_pane *cp, size_t limit)
uint64_t age, t = get_timer();
wp = control_window_pane(c, cp->pane);
if (wp == NULL || wp->fd == -1) {
if (wp == NULL) {
TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
TAILQ_REMOVE(&cp->blocks, cb, entry);
control_free_block(cs, cb);
@ -775,16 +775,13 @@ control_start(struct client *c)
cs->read_event = bufferevent_new(c->fd, control_read_callback,
control_write_callback, control_error_callback, c);
if (cs->read_event == NULL)
fatalx("out of memory");
bufferevent_enable(cs->read_event, EV_READ);
if (c->flags & CLIENT_CONTROLCONTROL)
cs->write_event = cs->read_event;
else {
cs->write_event = bufferevent_new(c->out_fd, NULL,
control_write_callback, control_error_callback, c);
if (cs->write_event == NULL)
fatalx("out of memory");
}
bufferevent_setwatermark(cs->write_event, EV_WRITE, CONTROL_BUFFER_LOW,
0);
@ -795,13 +792,6 @@ control_start(struct client *c)
}
}
/* Control client ready. */
void
control_ready(struct client *c)
{
bufferevent_enable(c->control_state->read_event, EV_READ);
}
/* Discard all output for a client. */
void
control_discard(struct client *c)
@ -874,7 +864,7 @@ control_check_subs_pane(struct client *c, struct control_sub *csub)
struct control_sub_pane *csp, find;
wp = window_pane_find_by_id(csub->id);
if (wp == NULL || wp->fd == -1)
if (wp == NULL)
return;
w = wp->window;

View File

@ -182,11 +182,9 @@ void
environ_update(struct options *oo, struct environ *src, struct environ *dst)
{
struct environ_entry *envent;
struct environ_entry *envent1;
struct options_entry *o;
struct options_array_item *a;
union options_value *ov;
int found;
o = options_get(oo, "update-environment");
if (o == NULL)
@ -194,15 +192,14 @@ environ_update(struct options *oo, struct environ *src, struct environ *dst)
a = options_array_first(o);
while (a != NULL) {
ov = options_array_item_value(a);
found = 0;
RB_FOREACH_SAFE(envent, environ, src, envent1) {
if (fnmatch(ov->string, envent->name, 0) == 0) {
environ_set(dst, envent->name, 0, "%s", envent->value);
found = 1;
}
RB_FOREACH(envent, environ, src) {
if (fnmatch(ov->string, envent->name, 0) == 0)
break;
}
if (!found)
if (envent == NULL)
environ_clear(dst, ov->string);
else
environ_set(dst, envent->name, 0, "%s", envent->value);
a = options_array_next(a);
}
}
@ -264,12 +261,6 @@ environ_for_session(struct session *s, int no_TERM)
environ_set(env, "TERM_PROGRAM_VERSION", 0, "%s", getversion());
}
#ifdef HAVE_SYSTEMD
environ_clear(env, "LISTEN_PID");
environ_clear(env, "LISTEN_FDS");
environ_clear(env, "LISTEN_FDNAMES");
#endif
if (s != NULL)
idx = s->id;
else

View File

@ -14,7 +14,7 @@ set -g status-bg red
%endif
# Enable RGB colour if running in xterm(1)
set-option -sa terminal-features ",xterm*:RGB"
set-option -sa terminal-overrides ",xterm*:Tc"
# Change the default $TERM to tmux-256color
set -g default-terminal "tmux-256color"
@ -61,7 +61,7 @@ bind y set synchronize-panes\; display 'synchronize-panes #{?synchronize-panes,o
# should be started with "tmux attach" rather than "tmux new"
new -d -s0 -nirssi 'exec irssi'
set -t0:0 monitor-activity on
set -t0:0 aggressive-resize on
set -t0:0 aggressive-resize on
neww -d -ntodo 'exec emacs ~/TODO'
setw -t0:1 aggressive-resize on
neww -d -nmutt 'exec mutt'

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