aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore17
-rw-r--r--.mailmap24
-rw-r--r--CHANGES1757
-rw-r--r--FAQ400
-rw-r--r--Makefile139
-rw-r--r--Makefile.am248
-rw-r--r--README60
-rw-r--r--SYNCING174
-rw-r--r--TODO155
-rw-r--r--arguments.c3
-rw-r--r--array.h2
-rw-r--r--attributes.c2
-rwxr-xr-xautogen.sh18
-rw-r--r--cfg.c2
-rw-r--r--client.c6
-rw-r--r--clock.c2
-rw-r--r--cmd-attach-session.c2
-rw-r--r--cmd-bind-key.c2
-rw-r--r--cmd-break-pane.c2
-rw-r--r--cmd-capture-pane.c2
-rw-r--r--cmd-choose-buffer.c2
-rw-r--r--cmd-choose-client.c2
-rw-r--r--cmd-choose-tree.c2
-rw-r--r--cmd-clear-history.c2
-rw-r--r--cmd-clock-mode.c2
-rw-r--r--cmd-command-prompt.c2
-rw-r--r--cmd-confirm-before.c2
-rw-r--r--cmd-copy-mode.c2
-rw-r--r--cmd-delete-buffer.c2
-rw-r--r--cmd-detach-client.c2
-rw-r--r--cmd-display-message.c2
-rw-r--r--cmd-display-panes.c2
-rw-r--r--cmd-find-window.c2
-rw-r--r--cmd-has-session.c2
-rw-r--r--cmd-if-shell.c2
-rw-r--r--cmd-join-pane.c3
-rw-r--r--cmd-kill-pane.c2
-rw-r--r--cmd-kill-server.c2
-rw-r--r--cmd-kill-session.c2
-rw-r--r--cmd-kill-window.c2
-rw-r--r--cmd-link-window.c2
-rw-r--r--cmd-list-buffers.c2
-rw-r--r--cmd-list-clients.c2
-rw-r--r--cmd-list-commands.c2
-rw-r--r--cmd-list-keys.c2
-rw-r--r--cmd-list-panes.c2
-rw-r--r--cmd-list-sessions.c2
-rw-r--r--cmd-list-windows.c2
-rw-r--r--cmd-list.c2
-rw-r--r--cmd-load-buffer.c2
-rw-r--r--cmd-lock-server.c2
-rw-r--r--cmd-move-window.c2
-rw-r--r--cmd-new-session.c2
-rw-r--r--cmd-new-window.c2
-rw-r--r--cmd-paste-buffer.c3
-rw-r--r--cmd-pipe-pane.c3
-rw-r--r--cmd-queue.c2
-rw-r--r--cmd-refresh-client.c2
-rw-r--r--cmd-rename-session.c2
-rw-r--r--cmd-rename-window.c2
-rw-r--r--cmd-resize-pane.c2
-rw-r--r--cmd-respawn-pane.c2
-rw-r--r--cmd-respawn-window.c2
-rw-r--r--cmd-rotate-window.c2
-rw-r--r--cmd-run-shell.c2
-rw-r--r--cmd-save-buffer.c3
-rw-r--r--cmd-select-layout.c2
-rw-r--r--cmd-select-pane.c2
-rw-r--r--cmd-select-window.c2
-rw-r--r--cmd-send-keys.c2
-rw-r--r--cmd-send-prefix.c57
-rw-r--r--cmd-server-info.c6
-rw-r--r--cmd-set-buffer.c2
-rw-r--r--cmd-set-environment.c2
-rw-r--r--cmd-set-option.c2
-rw-r--r--cmd-show-buffer.c112
-rw-r--r--cmd-show-environment.c2
-rw-r--r--cmd-show-messages.c2
-rw-r--r--cmd-show-options.c2
-rw-r--r--cmd-source-file.c2
-rw-r--r--cmd-split-window.c3
-rw-r--r--cmd-start-server.c2
-rw-r--r--cmd-string.c2
-rw-r--r--cmd-suspend-client.c2
-rw-r--r--cmd-swap-pane.c2
-rw-r--r--cmd-swap-window.c2
-rw-r--r--cmd-switch-client.c2
-rw-r--r--cmd-unbind-key.c2
-rw-r--r--cmd-unlink-window.c2
-rw-r--r--cmd-wait-for.c2
-rw-r--r--cmd.c5
-rw-r--r--colour.c2
-rw-r--r--compat.h245
-rw-r--r--compat/asprintf.c65
-rw-r--r--compat/b64_ntop.c182
-rw-r--r--compat/bitstring.h129
-rw-r--r--compat/closefrom.c111
-rw-r--r--compat/daemon.c66
-rw-r--r--compat/fgetln.c86
-rw-r--r--compat/forkpty-aix.c95
-rw-r--r--compat/forkpty-hpux.c89
-rw-r--r--compat/forkpty-sunos.c89
-rw-r--r--compat/getopt.c116
-rw-r--r--compat/imsg-buffer.c303
-rw-r--r--compat/imsg.c271
-rw-r--r--compat/imsg.h110
-rw-r--r--compat/queue.h568
-rw-r--r--compat/setenv.c49
-rw-r--r--compat/strcasestr.c61
-rw-r--r--compat/strlcat.c58
-rw-r--r--compat/strlcpy.c54
-rw-r--r--compat/strsep.c72
-rw-r--r--compat/strtonum.c68
-rw-r--r--compat/tree.h749
-rw-r--r--compat/unvis.c282
-rw-r--r--compat/vis.c221
-rw-r--r--compat/vis.h83
-rw-r--r--configure.ac481
-rw-r--r--control.c2
-rw-r--r--environ.c2
-rw-r--r--examples/bash_completion_tmux.sh105
-rw-r--r--examples/h-boetes.conf42
-rw-r--r--examples/n-marriott.conf110
-rw-r--r--examples/screen-keys.conf102
-rw-r--r--examples/t-williams.conf104
-rw-r--r--examples/tmux.vim126
-rw-r--r--examples/tmux_backup.sh81
-rw-r--r--examples/vim-keys.conf36
-rw-r--r--format.c6
-rw-r--r--grid-view.c2
-rw-r--r--grid.c2
-rw-r--r--input-keys.c3
-rw-r--r--input.c2
-rw-r--r--job.c3
-rw-r--r--key-bindings.c2
-rw-r--r--key-string.c2
-rw-r--r--layout-custom.c2
-rw-r--r--layout-set.c2
-rw-r--r--layout.c2
-rw-r--r--log.c2
-rw-r--r--mode-key.c2
-rw-r--r--names.c4
-rw-r--r--notify.c3
-rw-r--r--options-table.c3
-rw-r--r--options.c2
-rw-r--r--osdep-aix.c41
-rw-r--r--osdep-darwin.c80
-rw-r--r--osdep-dragonfly.c133
-rw-r--r--osdep-freebsd.c170
-rw-r--r--osdep-hpux.c41
-rw-r--r--osdep-linux.c97
-rw-r--r--osdep-netbsd.c137
-rw-r--r--osdep-openbsd.c (renamed from procname.c)18
-rw-r--r--osdep-sunos.c92
-rw-r--r--osdep-unknown.c41
-rw-r--r--paste.c3
-rw-r--r--resize.c2
-rw-r--r--screen-redraw.c2
-rw-r--r--screen-write.c2
-rw-r--r--screen.c3
-rw-r--r--server-client.c3
-rw-r--r--server-fn.c2
-rw-r--r--server-window.c2
-rw-r--r--server.c5
-rw-r--r--session.c3
-rw-r--r--signal.c2
-rw-r--r--status.c2
-rw-r--r--tmux.110
-rw-r--r--tmux.c22
-rw-r--r--tmux.h17
-rw-r--r--tools/256colors.pl63
-rw-r--r--tools/UTF-8-demo.txt212
-rw-r--r--tools/ansicode.txt779
-rw-r--r--tools/check-compat.sh5
-rw-r--r--tools/cmp-cvs.sh12
-rw-r--r--tools/fix-ids.sh8
-rw-r--r--tools/fuzz.c31
-rw-r--r--tools/putty-utf8.sh1
-rw-r--r--tty-acs.c2
-rw-r--r--tty-keys.c2
-rw-r--r--tty-term.c18
-rw-r--r--tty.c2
-rw-r--r--utf8.c4
-rw-r--r--window-choose.c2
-rw-r--r--window-clock.c2
-rw-r--r--window-copy.c2
-rw-r--r--window.c9
-rw-r--r--www/images/tmux3.pngbin0 -> 37945 bytes
-rw-r--r--www/images/tmux4.pngbin0 -> 6175 bytes
-rw-r--r--www/images/tmux5.pngbin0 -> 39923 bytes
-rw-r--r--www/index.html.in64
-rw-r--r--www/main.css50
-rw-r--r--xmalloc.c3
-rw-r--r--xterm-keys.c2
194 files changed, 10513 insertions, 485 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..c3906ada
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+*.o
+*~
+*.diff
+*.patch
+*.core
+core
+tags
+.deps/
+aclocal.m4
+autom4te.cache/
+config.log
+config.status
+etc/
+tmux
+Makefile
+Makefile.in
+configure
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 00000000..a7a401ff
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,24 @@
+Bob Beck <beck@openbsd.org> beck <beck>
+Igor Sobrado <sobrado@openbsd.org> sobrado <sobrado>
+Jacek Masiulaniec <jacekm@openbsd.org> jacekm <jacekm>
+Jason McIntyre <jmc@openbsd.org> jcm <jcm>
+Joel Sing <jsing@openbsd.org> jsing <jsing>
+Marc Espie <espie@openbsd.org> espie <espie>
+Matthew Dempsky <matthew@openbsd.org> matthew <matthew>
+Matthias Kilian <kili@openbsd.org> kili <kili>
+Matthieu Herrb <matthieu@openbsd.org> matthieu <matthieu>
+Miod Vallat <miod@openbsd.org> miod <miod>
+Nicholas Marriott <nicm@openbsd.org> nicm <nicm>
+Nicholas Marriott <nicm@openbsd.org> no_author <no_author@example.org>
+<nicm@openbsd.org> <nicholas.marriott@gmail.com>
+Okan Demirmen <okan@openbsd.org> okan <okan>
+Philip Guenther <guenther@openbsd.org> guenther <guenther>
+Pierre-Yves Ritschard <pyr@openbsd.org> pyr <pyr>
+Ray Lai <ray@openbsd.org> ray <ray>
+Ryan McBride <mcbride@openbsd.org> mcbride <mcbride>
+Stefan Sperling <stsp@openbsd.org> stsp <stsp>
+Stuart Henderson <sthen@openbsd.org> sthen <sthen>
+Ted Unangst <tedu@openbsd.org> tedu <tedu>
+Theo Deraadt <deraadt@openbsd.org> deraadt <deraadt>
+Thomas Adam <thomas@xteddy.org> Thomas <thomas@xteddy.org>
+William Yodlowsky <william@openbsd.org> william <william>
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 00000000..db0abf87
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,1757 @@
+CHANGES FROM 1.6 to 1.7, 13 October 2012
+
+* tmux configuration files now support line-continuation with a "\" at the
+ end of a line.
+* New option status-position to move the status line to the top or bottom of
+ the screen.
+* Enforce history-limit option when clearing the screen.
+* Give each window a unique id, like panes but prefixed with @.
+* Add pane id to each pane in layout description (while still accepting
+ the old form).
+* Provide defined ways to set the various default-path possibilities: ~
+ for home directory, . for server start directory, - for session start
+ directory and empty for the pane's working directory (the default). All
+ can also be used as part of a relative path (eg -/foo). Also provide -c
+ flags to neww and splitw to override default-path setting.
+* Add -l flag to send-keys to send input literally (without translating
+ key names).
+* Allow a single option to be specified to show-options to show just that
+ option.
+* New command "move-pane" (like join-pane but allows the same window).
+* join-pane and move-pane commands learn "-b" option to place the pane to
+ the left or above.
+* Support for bracketed-paste mode.
+* Allow send-keys command to accept hex values.
+* Add locking around "start-server" to avoid race-conditions.
+* break-pane learns -P/-F arguments for display formatting.
+* set-option learns "-q" to make it quiet, and not print out anything.
+* copy mode learns "wrap-search" option.
+* Add a simple form of output rate limiting by counting the number of
+ certain C0 sequences (linefeeds, backspaces, carriage returns) and if it
+ exceeds a threshold (current default 250/millisecond), start to redraw
+ the pane every 100 milliseconds instead of making each change as it
+ comes. Two configuration options - c0-change-trigger and
+ c0-change-interval.
+* find-window learns new flags: "-C", "-N", "-T" to match against either or
+ all of a window's content, name, or title. Defaults to all three options
+ if none specified.
+* find-window automatically selects the appropriate pane for the found
+ matches.
+* show-environment can now accept one option to show that environment value.
+* Exit mouse mode when end-of-screen reached when scrolling with the mouse
+ wheel.
+* select-layout learns -u and -U for layout history stacks.
+* kill-window, detach-client, kill-session all learn "-a" option for
+ killing all but the current thing specified.
+* move-window learns "-r" option to renumber window sequentially in a
+ session.
+* New session option "renumber-windows" to automatically renumber windows in
+ a session when a window is closed. (see "move-window -r").
+* Only enter copy-mode on scroll up.
+* choose-* and list-* commands all use "-F" for format specifiers.
+* When spawning external commands, the value from the "default-shell" option
+ is now used, rather than assuming /bin/sh.
+* New choose-tree command to render window/sessions as a tree for selection.
+* display-message learns new format options.
+* For linked-windows across sessions, all flags for that window are now
+ cleared across sessions.
+* Lots and lots of bug fixes, fixing memory-leaks, etc.
+* Various manpage improvements.
+
+CHANGES FROM 1.5 TO 1.6, 23 January 2012
+
+* Extend the mode-mouse option to add a third choice which means the mouse
+ does not enter copy mode.
+* Add a -r flag to switch-client to toggle the client read-only flag.
+* Add pane-base-index option.
+* Support \ for line continuation in the configuration file.
+* Framework for more powerful formatting of command output and use it for
+ list-{panes,windows,sessions}. This allows more descriptive replacements
+ (such as #{session_name}) and conditionals.
+* Mark dead panes with some text saying they are dead.
+* Reject $SHELL if it is not a full path.
+* Add -S option to refresh-client to redraw status line.
+* Add an else clause for if-shell.
+* Try to resolve relative paths for loadb and saveb (first, using client
+ working directory, if any, then default-path or session working directory).
+* Support for \e[3J to clear the history and send the corresponding
+ terminfo code (E3) before locking.
+* When in copy mode, make repeat count indicate buffer to replace, if used.
+* Add screen*:XT to terminal-overrides for tmux-in-tmux.
+* Status-line message attributes added.
+* Move word-separators to be a session rather than window option.
+* Change the way the working directory for new processes is discovered. If
+ default-path isn't empty, it is used. Otherwise, if a new window is created
+ from the command-line, the working directory of the client is used. If not,
+ platform specific code is used to retrieve the current working directory
+ of the process in the active pane. If that fails, the directory where the
+ session was created is used, instead.
+* Do not change the current pane if both mouse-select-{pane,window} are
+ enabled.
+* Add \033[s and \033[u to save and restore cursor position.
+* Allow $HOME to be used as default-path.
+* Add CNL and CPL escape sequences.
+* Calculate last position correctly for UTF-8 wide characters.
+* Add an option allow-rename to disable the window rename escape sequence.
+* Attributes for each type of status-line alert (ie bell, content and
+ activity) added. Therefore, remove the superfluous options
+ window-status-alert-{attr,bg,fg}.
+* Add a -R flag to send-keys to reset the terminal.
+* Add strings to allow the aixterm bright colours to be used when
+ configuring colours.
+* Drop the ability to have a list of keys in the prefix in favour of two
+ separate options, prefix and prefix2.
+* Flag -2 added to send-prefix to send the secondary prefix key.
+* Show pane size in top right of display panes mode.
+* Some memory leaks plugged.
+* More command-prompt editing improvements.
+* Various manpage improvements.
+* More Vi mode improvements.
+
+CHANGES FROM 1.4 TO 1.5, 09 July 2011
+
+* Support xterm mouse modes 1002 and 1003.
+* Change from a per-session stack of buffers to one global stack. This renders
+ copy-buffer useless and makes buffer-limit now a server option.
+* Fix most-recently-used choice by avoiding reset the activity timer for
+ unattached sessions every second.
+* Add a -P option to new-window and split-window to print the new window or
+ pane index in target form (useful to pass it into other commands).
+* Handle a # at the end of a replacement string (such as status-left)
+ correctly.
+* Support for UTF-8 mouse input (\033[1005h) which was added in xterm 262.
+ If the new mouse-utf8 option is on, UTF-8 mouse input is enabled for all
+ UTF-8 terminals. The option defaults to on if LANG etc are set in the same
+ manner as the utf8 option.
+* Support for HP-UX.
+* Accept colours of the hex form #ffffff and translate to the nearest from the
+ xterm(1) 256-colour set.
+* Clear the non-blocking IO flag (O_NONBLOCK) on the stdio file descriptors
+ before closing them (fixes things like "tmux ls && cat").
+* Use TMPDIR if set.
+* Fix next and previous session functions to actually work.
+* Support -x and -y for new-session to specify the initial size of the window
+ if created detached with -d.
+* Make bind-key accept characters with the top-bit-set and print them as octal.
+* Set $TMUX without the session when background jobs are run.
+* Simplify the way jobs work and drop the persist type, so all jobs are
+ fire-and-forget.
+* Accept tcgetattr/tcsetattr(3) failure, fixes problems with fatal() if the
+ terminal disappears while locked.
+* Add a -P option to detach to HUP the client's parent process (usually causing
+ it to exit as well).
+* Support passing through escape sequences to the underlying terminal by using
+ DCS with a "tmux;" prefix.
+* Prevent tiled producing a corrupt layout when only one column is needed.
+* Give each pane created in a tmux server a unique id (starting from 0), put it
+ in the TMUX_PANE environment variable and accept it as a target.
+* Allow a start and end line to be specified for capture-pane which may be
+ negative to capture part of the history.
+* Add -a and -s options to lsp to list all panes in the server or session
+ respectively. Likewise add -s to lsw.
+* Change -t on display-message to be target-pane for the #[A-Z] replacements
+ and add -c as target-client.
+* The attach-session command now prefers the most recently used unattached
+ session.
+* Add -s option to detach-client to detach all clients attached to a session.
+* Add -t to list-clients.
+* Change window with mouse wheel over status line if mouse-select-window is on.
+* When mode-mouse is on, automatically enter copy mode when the mouse is
+ dragged or the mouse wheel is used. Also exit copy mode when the mouse wheel
+ is scrolled off the bottom.
+* Provide #h character pair for short hostname (no domain).
+* Don't use strnvis(3) for the title as it breaks UTF-8.
+* Use the tsl and fsl terminfo(5) capabilities to update terminal title and
+ automatically fill them in on terminals with the XT capability (which means
+ their title setting is xterm-compatible).
+* Add a new option, mouse-resize-pane. When on, panes may be resized by
+ dragging their borders.
+* Fix crash by resetting last pane on {break,swap}-pane across windows.
+* Add three new copy-mode commands - select-line, copy-line, copy-end-of-line.
+* Support setting the xterm clipboard when copying from copy mode using the
+ xterm escape sequence for the purpose (if xterm is configured to allow it).
+* Support xterm(1) cursor colour change sequences through terminfo(5) Cc
+ (set) and Cr (reset) extensions.
+* Support DECSCUSR sequence to set the cursor style with two new terminfo(5)
+ extensions, Cs and Csr.
+* Make the command-prompt custom prompts recognize the status-left option
+ character pairs.
+* Add a respawn-pane command.
+* Add a couple of extra xterm-style keys that gnome terminal provides.
+* Allow the initial context on prompts to be set with the new -I option to
+ command-prompt. Include the current window and session name in the prompt
+ when renaming and add a new key binding ($) for rename session.
+* Option bell-on-alert added to trigger the terminal bell when there is an
+ alert.
+* Change the list-keys format so that it shows the keys using actual tmux
+ commands which should be able to be directly copied into the config file.
+* Show full targets for lsp/lsw -a.
+* Make confirm-before prompt customizable with -p option like command-prompt
+ and add the character pairs #W and #P to the default kill-{pane,window}
+ prompts.
+* Avoid sending data to suspended/locked clients.
+* Small memory leaks in error paths plugged.
+* Vi mode improvements.
+
+CHANGES FROM 1.3 TO 1.4, 27 December 2010
+
+* Window bell reporting fixed.
+* Show which pane is active in the list-panes output.
+* Backoff reworked.
+* Prevent the server from dying when switching into copy mode when already
+ in a different mode.
+* Reset running jobs when the status line is enabled or disabled.
+* Simplify xterm modifier detection.
+* Avoid crashing in copy mode if the screen size is too small for the
+ indicator.
+* Flags -n and -p added to switch-client.
+* Use UTF-8 line drawing characters on UTF-8 terminals, thus fixing some
+ terminals (eg putty) which disable the vt100 ACS mode switching sequences
+ in UTF-8 mode. On terminals without ACS, use ASCII equivalents.
+* New server option exit-unattached added.
+* New session option destroy-unattached added.
+* Fall back on normal session choice method if $TMUX exists but is invalid
+ rather than rejecting.
+* Mark repeating keys with "(repeat)" in the key list.
+* When removing a pane, don't change the active pane unless the active pane
+ is actually the one being removed.
+* New command last-pane added.
+* AIX fixes.
+* Flag -a added to unbind-key.
+* Add XAUTHORITY to update-environment.
+* More info regarding window and pane flags is now shown in list-*.
+* If VISUAL or EDITOR contains "vi" configure mode-keys and status-key to vi.
+* New window option monitor-silence and session option visual-silence added.
+* In the built-in layouts distribute the panes more evenly.
+* Set the default value of main-pane-width to 80 instead of 81.
+* Command-line flag -V added.
+* Instead of keeping a per-client prompt history make it global.
+* Fix rectangle copy to behave like emacs (the cursor is not part of the
+ selection on the right edge but on the left it is).
+* Flag -l added to switch-client.
+* Retrieve environment variables from the global environment rather than
+ getenv(3), thus allowing them to be updated during the configuration file.
+* New window options other-pane-{height,width} added.
+* More minor bugs fixed and manpage improvements.
+
+CHANGES FROM 1.2 TO 1.3, 18 July 2010
+
+* New input parser.
+* Flags to move through panes -UDLR added to select-pane.
+* Commands up-pane, and down-pane removed, since equivalent behaviour is now
+ available through the target flag (-t:+ and -t:-).
+* Jump-forward/backward in copy move (based on vi's F, and f commands).
+* Make paste-buffer accept a pane as a target.
+* Flag -a added to new-window to insert a window after an existing one, moving
+ windows up if necessary.
+* Merge more mode into copy mode.
+* Run job commands explicitly in the global environment (which can be modified
+ with setenv -g), rather than with the environment tmux started with.
+* Use the machine's hostname as the default title, instead of an empty string.
+* Prevent double free if the window option remain-on-exit is set.
+* Key string conversions rewritten.
+* Mark zombie windows as dead in the choose-window list.
+* Tiled layout added.
+* Signal handling reworked.
+* Reset SIGCHLD after fork to fix problems with some shells.
+* Select-prompt command removed. Therefore, bound ' to command-prompt -p index
+ "select-window -t:%%" by default.
+* Catch SIGHUP and terminate if running as a client, thus avoiding clients from
+ being left hanging around when, for instance, a SSH session is disconnected.
+* Solaris 9 fixes (such as adding compat {get,set}env(3) code).
+* Accept none instead of default for attributes.
+* Window options window-status-alert-{alert,bg,fg} added.
+* Flag -s added to the paste-buffer command to specify a custom separator.
+* Allow dragging to make a selection in copy mode if the mode-mouse option is
+ set.
+* Support the mouse scroll wheel.
+* Make pipe-pane accept special character sequences (eg #I).
+* Fix problems with window sizing when starting tmux from .xinitrc.
+* Give tmux sockets (but not the containing folder) group permissions.
+* Extend the target flags (ie -t) to accept an offset (for example -t:+2), and
+ make it wrap windows, and panes.
+* New command choose-buffer added.
+* New server option detach-on-destroy to set what happens to a client when the
+ session it is attached to is destroyed. If on (default), the client is
+ detached. Otherwise, the client is switched to the most recently active of
+ the remaining sessions.
+* The commands load-buffer, and save-buffer now accept a dash (-) as the file
+ to read from stdin, or write to stdout.
+* Custom layouts added.
+* Additional code reduction, bug fixes, and manpage enhancements.
+
+CHANGES FROM 1.1 TO 1.2, 10 March 2010
+
+* Switch to libevent.
+* Emulate the ri (reverse index) capability, ergo allowing tmux to at least
+ start on Sun consoles (TERM=sun, or sun-color).
+* Assign each entry a number, or lowercase letter in choose mode, and accept
+ that as a shortcut key.
+* Permit top-bit-set characters to be entered in the status line.
+* Mark no-prefix keys with (no prefix), rather than [] in list-keys.
+* New command show-messages (alias showmsgs), and new session option
+ message-limit, to show a per-client log of status lines messages up to the
+ number defined by message-limit.
+* Do not interpret #() for display-message to avoid leaking commands.
+* New window options window-status-format, and window-status-current-format to
+ control the format of each window in the status line.
+* Add a -p flag to display-message to print the output, instead of displaying
+ it in the status line.
+* Emulate il1, dl1, ich1 to run with vt100 feature set.
+* New command capture-pane (alias capturep) to copy the entire pane contents
+ to a paste buffer.
+* Avoid duplicating code by adding a -w flag to set-option, and show-options to
+ set, and show window options. The commands set-window-option, and
+ show-window-options are now aliases.
+* Panes can now be referred to as top, bottom, top-left, etc.
+* Add server-wide options, which can be set with set-option -s, and shown with
+ show-options -s.
+* New server option quiet (like -q from the command line).
+* New server option escape-time to set the timeout used to detect if escapes
+ are alone, part of a function key, or meta sequence.
+* New session options pane-active-border-bg, pane-active-border-fg,
+ pane-border-bg, and pane-border-fg to set pane colours.
+* Make split-window accept a pane target, instead of a window.
+* New command join-pane (alias joinp) to split, and move an existing pane into
+ the space (the opposite of break-pane), thus simplifying calls to
+ split-window, followed by move-window.
+* Permit S- prefix on keys for shift when the terminal/terminfo supports them.
+* Window targets (-t flag) can now refer to the last window (!), next (+), and
+ previous (-) window by number.
+* Mode keys to jump to the bottom/top of history, end of the next word, scroll
+ up/down, and reverse search in copy mode.
+* New session option display-panes-active-colour to display the active pane in
+ a different colour with the display-panes command.
+* Read the socket path from $TMUX if it's present, and -L, and -S are not
+ given.
+* Vi-style mode keys B, W, and E to navigate between words in copy mode.
+* Start in more mode when configuration file errors are detected.
+* Rectangle copy support added.
+* If attach-session was specified with the -r flag, make the client read-only.
+* Per-window alternate-screen option.
+* Make load-buffer work with FIFOs.
+* New window option word-separators to set the characters considered as word
+ separators in copy mode.
+* Permit keys in copy mode to be prefixed by a repeat count, entered with [1-9]
+ in vi mode, or M-[1-9] in emacs mode.
+* utf8 improvements.
+* As usual, additional code reduction, bug fixes, and manpage enhancements.
+
+CHANGES FROM 1.0 TO 1.1, 05 November 2009
+
+* New run-shell (alias run) command to run an external command without a
+ window, capture it's stdout, and send it to output mode.
+* Ability to define multiple prefix keys.
+* Internal locking mechanism removed. Instead, detach each client and run the
+ external command specified in the new session option lock-command (by default
+ lock -np), thus allowing the system password to be used.
+* set-password command, and -U command line flag removed per the above change.
+* Add support for -c command line flag to execute a shell command.
+* New lock-client (alias lockc), and lock-session (alias locks) commands to
+ lock a particular client, or all clients attached to a session.
+* Support C-n/C-p/C-v/M-v with emacs keys in choice mode.
+* Use : for goto line rather than g in vi mode.
+* Try to guess which client to use when no target client was specified. Finds
+ the current session, and if only one client is present, use it. Otherwise,
+ return the most recently used client.
+* Make C-Down/C-Up in copy mode scroll the screen down/up one line without
+ moving the cursor.
+* Scroll mode superseded by copy mode.
+* New synchronize-panes window option to send all input to all other panes in
+ the same window.
+* New lock-server session option to lock, when off (on by default), each
+ session when it has been idle for the lock-after-time setting. When on, the
+ entire server locks when all sessions have been idle for their individual
+ lock-after-time setting.
+* Add support for grouped sessions which have independent name, options,
+ current window, but where the linked windows are synchronized (ie creating,
+ killing windows are mirrored between the sessions). A grouped session may be
+ created by passing -t to new-session.
+* New mouse-select-pane session option to select the current pane with the
+ mouse.
+* Queue, and run commands in the background for if-shell, status-left,
+ status-right, and #() by starting each once every status-interval. Adds the
+ capability to call some programs which would previously cause the server to
+ hang (eg sleep/tmux). It also avoids running commands excessively (ie if used
+ multiple times, it will be run only once).
+* When a window is zombified and automatic-rename is on, append [dead] to the
+ name.
+* Split list-panes (alias lsp) off from list-windows.
+* New pipe-pane (alias pipep) to redirect a pane output to an external command.
+* Support for automatic-renames for Solaris.
+* Permit attributes to be turned off in #[] by prefixing with no (eg nobright).
+* Add H/M/L in vi mode, and M-R/M-r in emacs to move the cursor to the top,
+ middle, and bottom of the screen.
+* -a option added to kill-pane to kill all except current pane.
+* The -d command line flag is now gone (can be replaced by terminal-overrides).
+ Just use op/AX to detect default colours.
+* input/tty/utf8 improvements.
+* xterm-keys rewrite.
+* Additional code reduction, and bug fixes.
+
+CHANGES FROM 0.9 TO 1.0, 20 Sept 2009
+
+* Option to alter the format of the window title set by tmux.
+* Backoff for a while after multiple incorrect password attempts.
+* Quick display of pane numbers (C-b q).
+* Better choose-window, choose-session commands and a new choose-client command.
+* Option to request multiple responses when using command-prompt.
+* Improved environment handling.
+* Combine wrapped lines when pasting.
+* Option to override terminal settings (terminal-overrides).
+* Use the full range of ACS characters for drawing pane separator lines.
+* Customisable mode keys.
+* Status line colour options, with embedded colours in status-left/right, and
+ an option to centre the window list.
+* Much improved layouts, including both horizontal and vertical splitting.
+* Optional visual bell, activity and content indications.
+* Set the utf8 and status-utf8 options when the server is started with -u.
+* display-message command to show a message in the status line, by default some
+ information about the current window.
+* Improved current process detection on NetBSD.
+* unlink-window -k is now the same as kill-window.
+* attach-session now works from inside tmux.
+* A system-wide configuration file, /etc/tmux.conf.
+* A number of new commands in copy mode, including searching.
+* Panes are now specified using the target (-t) notation.
+* -t now accepts fnmatch(3) patterns and looks for prefixes.
+* Translate \r into \n when pasting.
+* Support for binding commands to keys without the prefix key
+* Support for alternate screen (terminfo smcup/rmcup).
+* Maintain data that goes off screen after reducing the window size, so it can
+ be restored when the size is increased again.
+* New if-shell command to test a shell command before running a tmux command.
+* tmux now works as the shell.
+* Man page reorganisation.
+* Many minor additions, much code tidying and several bug fixes.
+
+CHANGES FROM 0.8 TO 0.9, 01 July 2009
+
+* Major changes to build infrastructure: cleanup of makefiles and addition
+ of a configure script.
+* monitor-content window option to monitor a window for a specific fnmatch(3)
+ pattern. The find-window command also now accepts fnmatch(3) patterns.
+* previous-layout and select-layout commands, and a main-horizontal layout.
+* Recreate the server socket on SIGUSR1.
+* clear-history command.
+* Use ACS line drawing characters for pane separator lines.
+* UTF-8 improvements, and code to detect UTF-8 support by looking at
+ environment variables.
+* The resize-pane-up and resize-pane-down commands are now merged together
+ into a new resize-pane command with -U and -D flags.
+* confirm-before command to request a yes/no answer before executing dangerous
+ commands.
+* Status line bug fixes, support for UTF-8 (status-utf8 option), and a key to
+ paste from the paste buffer.
+* Support for some additional escape sequences and terminal features, including
+ better support for insert mode and tab stops.
+* Improved window resizing behaviour, modelled after xterm.
+* Some code reduction and a number of miscellaneous bug fixes.
+
+================================================================================
+
+On 01 June 2009, tmux was imported into the OpenBSD base system. From this date
+onward changes are logged as part of the normal CVS commit message to either
+OpenBSD or SourceForge CVS. This file will be updated to contain a summary of
+major changes with each release, and to mention important configuration or
+command syntax changes during development.
+
+The list of older changes is below.
+
+================================================================================
+
+21 May 2009
+
+* stat(2) files before trying to load them to avoid problems, for example
+ with "source-file /dev/zero".
+
+19 May 2009
+
+* Try to guess if the window is UTF-8 by outputting a three-byte UTF-8 wide
+ character and seeing how much the cursor moves. Currently tries to figure out
+ if this works by some stupid checks on the terminal, these need to be
+ rethought. Also might be better using a width 1 character rather than width 2.
+* If LANG contains "UTF-8", assume the terminal supports UTF-8, on the grounds
+ that anyone who configures it probably wants UTF-8. Not certain if this is
+ a perfect idea but let's see if it causes any problems.
+* New window option: monitor-content. Searches for a string in a window and if
+ it matches, highlight the status line.
+
+18 May 2009
+
+* main-horizontal layout and main-pane-height option to match vertical.
+* New window option main-pane-width to set the width of the large left pane with
+ main-vertical (was left-vertical) layout.
+* Lots of layout cleanup. manual layout is now manual-vertical.
+
+16 May 2009
+
+* select-layout command and a few default key bindings (M-0, M-1, M-2, M-9) to
+ select layouts.
+* Recreate server socket on SIGUSR1, per SF feature request 2792533.
+
+14 May 2009
+
+* Keys in status line (p in vi mode, M-y in emacs) to paste the first line
+ of the upper paste buffer. Suggested by Dan Colish.
+* clear-history command to clear a pane's history.
+* Don't force wrapping with \n when asked, let the cursor code figure it out.
+ Should fix terminals which use this to detect line breaks.
+* Major cleanup and restructuring of build infrastructure. Still separate files
+ for GNU and BSD make, but they are now hugely simplified at the expense of
+ adding a configure script which must be run before make. Now build and
+ install with:
+
+ $ ./configure && make && sudo make install
+
+04 May 2009
+
+* Use ACS line drawing characters for pane separator lines.
+
+30 April 2009
+
+* Support command sequences without a space before the semicolon, for example
+ "neww; neww" now works as well as "neww ; neww". "neww;neww" is still an
+ error.
+* previous-layout command.
+* Display the layout name in window lists.
+* Merge resize-pane-up and resize-pane-down into resize-pane with -U and -D
+ flags.
+
+29 April 2009
+
+* Get rid of compat/vis.* - only one function was used which is easily
+ replaced,and less compat code == good.
+
+27 April 2009
+
+* Avoid using the prompt history when the server is locked, and prevent any
+ input entered from being added to the client's prompt history.
+* New command, confirm-before (alias confirm), which asks for confirmation
+ before executing a command. Bound "&" and "x" by default to confirm-before
+ "kill-window" and confirm-before "kill-pane", respectively.
+
+23 April 2009
+
+* Support NEL, yet another way of making newline. Fixes the output from some
+ Gentoo packaging thing. Reported by someone on SF then logs that allowed a
+ fix sent by tcunha.
+* Use the xenl terminfo flag to detect early-wrap terminals like the FreeBSD
+ console. Many thanks for a very informative email from Christian Weisgerber.
+
+21 April 2009
+
+* tmux 0.8 released.
+
+17 April 2009
+
+* Remove the right number of characters from the buffer when escape then
+ a cursor key (or other key prefixed by \033) is pressed. Reported by
+ Stuart Henderson.
+
+03 April 2009
+
+* rotate-window command. -U flag (default) for up, -D flag for down.
+
+02 April 2009
+
+* Change scroll/pane redraws to only redraw the single pane affected rather
+ than the entire window.
+* If redrawing the region would mean redrawing > half the pane, just schedule
+ to redraw the entire window. Also add a flag to skip updating the window any
+ further if it is scheduled to be redrawn. This has the effect of batching
+ multiple redraws together.
+
+01 April 2009
+
+* Basic horizontal splitting and layout management. Still some redraw and other
+ issues - particularly, don't mix with manual pane resizing, be careful when
+ viewing from multiple clients and don't expect shell windows to redraw very
+ well after the layout is changed; generally cycling the layout a few times
+ will fix most problems. Getting this in for testing while I think about how
+ to deal with manual mode.
+
+ Split window as normal and cycle the layouts with C-b space. Some of the
+ layouts will work better when swap-pane comes along.
+
+31 March 2009
+
+* AIX port, thanks to cmihai for access to a box. Only tested on 6.1 with xlc
+ 10.1 (make sure CC is set). Needs GNU make and probably ncurses (didn't try
+ plain curses). Also won't build with DEBUG, so comment the FDEBUG=1 line in
+ GNUmakefile.
+* Draw a vertical line on the right when the window size is less than the
+ terminal size. This is partly to shake out any horizontal limit bugs on the
+ way to horizontal splitting/pane tiling. Currently a bit slow since it has to
+ do a lot of redrawing but hopefully that will improve as I get some better
+ ideas for how to do it.
+* Fix remaining problems with copy and paste and UTF-8.
+
+28 March 2009
+
+* Better UTF-8 support, including combined characters. Unicode data is now
+ stored as UTF-8 in a separate array, the code does a lookup into this every
+ time it gets to a UTF-8 cell. Zero width characters are just appended onto
+ the UTF-8 data for the previous cell. This also means that almost no bytes
+ extra are wasted non-Unicode data (yay).
+
+ Still some oddities, such as copy mode skips over wide characters in a
+ strange way, and the code could do with some tidying.
+* Key repeating is now a property of the key binding not of the command.
+ Repeat is turned on when the key is bound with the -r flag to bind-key.
+ next/previous-window no longer repeat by default as it turned out to annoy
+ me.
+
+27 March 2009
+
+* Clear using ED when redrawing the screen. I foolishly assumed using spaces
+ would be equivalent and terminals would pick up on this, but apparently not.
+ This fixes copy and paste in xterm/rxvt.
+* Sockets in /tmp are now created in a subdirectory named, tmux-UID, eg
+ tmux-1000. The default socket is thus /tmp/tmux-UID/default. To start a
+ separate server, the new -L command line option should be used: this creates
+ a socket in the same directory with a different name ("-L main" will create
+ socket called "main"). -S should only be used to place the socket outside
+ /tmp. This makes sockets a little more secure and a bit more convenient to
+ use multiple servers.
+
+21 March 2009
+
+* New session flag "set-remain-on-exit" to set remain-on-exit flag for new
+ windows created in that session (like "remain-by-default" used to do). Not
+ perfectly happy about this, but until I can think of a good way to introduce
+ it generically (maybe a set of options in the session) this will do. Fixes
+ SF request 2527847.
+
+07 March 2009
+
+* Support for 88 colour terminals.
+* break-pane command to create a new window using an existing pane.
+
+02 March 2009
+
+* Make escape key timer work properly so escape+key can be used without
+ lightning fast key presses.
+
+13 February 2009
+
+* Redo mode keys slightly more cleanly and apply them to command prompt
+ editing. vi or emacs mode is controlled by the session option status-keys.
+
+12 February 2009
+
+* Looking up argv[0] is expensive, so just use p_comm for the window name which
+ is good enough. Also increase name update time to 500 ms.
+
+11 February 2009
+
+* Only use ri when actually at the top of the screen; just move the cursor up
+ otherwise.
+* FreeBSD's console wraps lines at $COLUMNS - 1 rather than $COLUMNS (the
+ cursor can never be beyond $COLUMNS - 1) and does not appear to support
+ changing this behaviour, or any of the obvious possibilities (turning off
+ right margin wrapping, insert mode). This is irritating, most notably because
+ it impossible to write to the very bottom-right of the screen without
+ scrolling. To work around this, if built on FreeBSD and run with a "cons"
+ $TERM, the bottom-right cell on the screen is omitted.
+* Emulate scroll regions (slowly) to support the few terminals which don't have
+ it (some of which don't really have any excuse).
+
+10 February 2009
+
+* No longer redraw the status line every status-interval unless it has actually
+ changed.
+
+08 February 2009
+
+* Don't treat empty arguments ("") differently when parsing configuration
+ file/command prompt rather than command line.
+* tmux 0.7 released.
+
+03 February 2009
+
+* New command, copy-buffer (alias copyb), to copy a session paste buffer to
+ another session.
+
+01 February 2009
+
+* The character pair #(command) may now contain (escaped) right parenthesis.
+
+30 January 2009
+
+* . now bound to "command-prompt 'move-window %%'" by default, from joshe.
+
+29 January 2009
+
+* Window options to set status line fg, bg and attributes for a single
+ window. Options are: window-status-fg, window-status-bg,
+ window-status-attr. Set to "default" to use the session status colours.
+
+ This allows quite neat things like:
+
+ $ cat ~/bin/xssh
+ #!/bin/sh
+
+ if [ ! -z "$TMUX" ]; then
+ case "$1" in
+ natalya)
+ tmux setw window-status-fg red >/dev/null
+ ;;
+ natasha)
+ tmux setw window-status-fg yellow >/dev/null
+ ;;
+ esac
+ fi
+ ssh "$@"
+ [ ! -z "$TMUX" ] && tmux setw -u window-status-fg >/dev/null
+ $ alias ssh="~/bin/xssh"
+
+* Support #(command) in status-left, and status-right, which is displayed as
+ the first line of command's output (e.g. set -g status-right
+ "#(whoami)@#(hostname -s)"). Commands with )s aren't supported.
+
+28 January 2009
+
+* Support mouse in copy mode to move cursor. Can't do anything else at the
+ moment until other mouse modes are handled.
+* Better support for at least the most common variant of mouse input: parse it
+ and adjust for different panes. Also support mouse in window/session choice
+ mode.
+
+27 January 2009
+
+* Bring back the fancy window titles with session/window names: it is easy to
+ work around problems with elinks (see FAQ).
+* -u flag to scroll-mode and copy-mode to start scrolled one page
+ up. scroll-mode -u is bound to prefix,page-up (ppage) by default.
+* Allow status, mode and message attributes to be changed by three new options:
+ status-attr, mode-attr, message-attr. A comma-separataed list is accepted
+ containing: bright, dim, underscore, blink, reverse, hidden, italics, for
+ example:
+
+ set -g status-attr bright,blink
+
+ From Josh Elsasser, thanks!
+
+26 January 2009
+
+* Be more clever about picking the right process to create the window name.
+* Don't balls up the terminal on UTF-8 combined characters. Don't support them
+ properly either - they are just discarded for the moment.
+
+25 January 2009
+
+* load-buffer command
+
+23 January 2009
+
+* Use reverse colours rather than swapping fg and bg for message, mode and
+ status line. This makes these usable on black and white terminals.
+* Better error messages when creating a session or window fails.
+* Oops. Return non-zero on error. Reported by Will Maier.
+
+21 January 2009
+
+* Handle SIGTERM (and kill-server which uses it), a bit more neatly - tidy
+ up properly and print a nicer message. Same effect though :-).
+* new-window now supports -k to kill target window if it exists.
+* Bring back split-window -p and -l options to specify the height a percentage
+ or as a number of lines.
+* Make window and session choice modes allow you to choose items in vi keys
+ mode (doh!). As a side-effect, this makes enter copy selection (as well
+ as C-w/M-w) when using emacs keys in copy mode. Reported by merdely.
+
+20 January 2009
+
+* Darwin support for automatic-rename from joshe; Darwin doesn't seem to have
+ a sane method of getting argv[0] and searching for the precise insane way
+ is too frustrating, so this just uses the executable name.
+* Try to change the window title to match the command running it in. This is
+ done by reading argv[0] from the process group leader of the group that owns
+ the tty (tcgetpgrp()). This can't be done portably so some OS-dependent code
+ is introduced (ugh); OpenBSD, FreeBSD and Linux are supported at the moment.
+
+ A new window flag, automatic-rename, is available: if this is set to off, the
+ window name is not changed. Specifying a name with the new-window,
+ new-session or rename-window commands will automatically set this flag to off
+ for the window in question. To disable it entirely set the option to off
+ globally (setw -g automatic-rename off).
+
+19 January 2009
+
+* Fix various stupid issues when the status line is turned off. Grr.
+* Use reverse attributes for clock and cursor, otherwise they do not
+ appear on black and white terminals.
+* An error in a command sequence now stops execution of that sequence.
+ Internally, each command code now passes a return code back rather than
+ talking to the calling client (if any) directly.
+* attach-session now tries to start the server if it isn't already started - if
+ no sessions are created in .tmux.conf this will cause an error.
+* Clean up starting server by making initial client get a special socketpair.
+
+18 January 2009
+
+* Unbreak UTF-8.
+* -a flag to next-window and previous-window to select the next or previous
+ window with activity or bell. Bound to M-n and M-p.
+* find-window command to search window names, titles and visible content (but
+ not history) for a string. If only one is found, the window is selected
+ otherwise a choice list is shown. This (as with the other choice commands)
+ only works from a key. Bound to "f" by default.
+* Cleaned up command printing code, also enclose arguments with spaces in "s.
+* Added command sequences. These are entered by separating each argument by a ;
+ argument (spaces on both sides), for example:
+
+ lsk ; lsc
+
+ To use a literal ; as the argument prefix it with \, for example:
+
+ bind x lsk \; lsc
+
+ Commands are executed from left to right. Also note that command sequences do
+ not support repeat-time repetition unless all commands making up the sequence
+ support it.
+* suspend-client command to suspend a client. Don't try to background it
+ though...
+* Mark attached sessions in sessions lists. Suggested by Simon Kuhnle.
+
+17 January 2009
+
+* tmux 0.6 released.
+
+15 January 2009
+
+* Support #H for hostname and #S for session name in status-left/right.
+* Two new commands, choose-window and choose-session which work only when bound
+ to a key and allow the window or session to be selected from a list. These
+ are now bound to "w" and "s" instead of the list commands.
+
+14 January 2009
+
+* Rework the prefix-time stuff. The option is now called repeat-time and
+ defaults to 500 ms. It only applies to a small subset of commands, currently:
+ up-pane, down-pane, next-window, previous-window, resize-pane-up,
+ resize-pane-down. These are the commands for which it is obviously useful,
+ having it for everything else was just bloody annoying.
+* The alt-up and alt-down keys now resize a pane by five lines at a time.
+* switch-pane is now select-pane and requires -p to select a pane. The
+ "o" key binding is changed to down-pane.
+* up-pane and down-pane commands, bound to arrow up and down by default.
+* Multiple vertical window splitting. Minimum pane size is four lines, an
+ (unhelpful) error will be shown if attempting to split a window with less
+ that eight lines. If the window is resized, as many panes are shown as can
+ fit without reducing them below four lines. There is (currently!) not a way
+ to show a hidden pane without making the window larger.
+
+ Note the -p and -l options to split-window are now gone, these may reappear
+ once I think them through again.
+* Server locking on inactivity (lock-after-time) is now disabled by default.
+
+13 January 2009
+
+* kill-pane command.
+
+12 January 2009
+
+* command-prompt now accepts a single argument, a template string. Any
+ occurrences of %% in this string are replaced by whatever is entered at the
+ prompt and the result is executed as a command. This allows things like (now
+ bound by default):
+
+ bind , command-prompt "rename-window %%"
+
+ Or my favourite:
+
+ bind x command-prompt "split-window 'man %%'"
+
+* Option to set prefix time, allowing multiple commands to be entered without
+ pressing the prefix key again, so long as they each typed within this time of
+ each other.
+* Yet more hacks for key handling. Think it is just about working now.
+* Two commands, resize-pane-up and resize-pane-down to resize a pane.
+* Make the window pane code handle panes of different sizes, and add a -l
+ and -p arguments to split-window to specify the new window size in lines
+ or as a percentage.
+
+11 January 2009
+
+* Vertical window splitting. Currently can only split a window into two panes.
+ New split-window command splits (bound to ") and switch-pane command (bound to
+ o) switches between panes.
+
+ close-pane, swap-pane commands are to follow. Also to come are pane resizing,
+ >2 panes, the ability to break a pane out to a full window and vice versa and
+ possibly horizontal splitting.
+
+ Panes are subelements of windows rather than being windows in their own
+ right. I tried to make them windows (so the splitting was at the session or
+ client level) but this rapidly became very complex and invasive. So in the
+ interests of having something working, I just made it so each window can have
+ two child processes instead of one (and it still took me 12 hours straight
+ coding). Now the concept is proven and much of the support code is there,
+ this may change in future if more flexibility is needed.
+* save-buffer command, from Tiago Cunha.
+
+10 January 2009
+
+* New option, lock-after-time. If there is no activity in the period specified
+ by this option (in seconds), tmux will lock the server. Default is 1800 (30
+ minutes), set to 0 to disable.
+* Server locking. Two new commands: set-password to set a password (a
+ preencrypted password may be specified with -c); and lock-server to lock the
+ server until the password is entered. Also an additional command line flag,
+ -U, to unlock from the shell. The default password is blank (any password
+ accepted). If specifying an encrypted password from encrypt(1) in .tmux.conf
+ with -c, don't forget to enclose it in single-quotes (') to prevent shell
+ variable expansion.
+* If a window is created from the command line, tmux will now use the same
+ current working directory for the new process. A new default-path option to
+ sets the working directory for processes created from keys or interactively
+ from the prompt.
+* New mode to display a large clock. Entered with clock-mode command (bound to
+ C-b t by default); two window options: clock-mode-colour and clock-mode-style
+ (12 or 24). This will probably be used as the basis for window locking.
+* New command, server-info, to show some server information and terminal
+ details.
+
+09 January 2009
+
+* Stop using ncurses variables and instead build a table of the codes we want
+ into an array for each terminal type. This makes the code a little more
+ untidy in places but gets rid of the awful global variables and calling
+ setterm all the time, and shoves all the ncurses-dependent mess into a single
+ file, tty-term.c. It also allows overriding single terminal codes, this is
+ used to fix rxvt on some platforms (where it is missing dch) and in future
+ may allow user customisation a la vim.
+* Update key handling code. Simplify, support ctrl properly and add a new
+ window option (xterm-keys) to output xterm key codes including ctrl and,
+ if available, alt and shift.
+
+08 January 2009
+
+* If built without DEBUG (the release versions), don't cause a fatal error if
+ the grid functions notice an input error, just log and ignore the
+ request. This might mean me getting shouted at less often when bugs kill
+ long-running sessions, at least in release versions.
+* Hopefully fix cursor out-of-bounds checking when writing to grid. When I
+ wrote the code I must have forgotten that the cursor can be one cell off the
+ right of the screen (yes, I know), so there were number of out-of-bounds/
+ overflow problems.
+
+07 January 2009
+
+* New flag to set and setw, -u, to unset an option (allowing it to inherit from)
+ the global options again.
+* Added more info messages for options changes.
+* A bit of tidying and reorganisation of options code.
+
+06 January 2009
+
+* Don't crash when backspacing if cursor is off the right of the screen,
+ reported by David Chisnall.
+* Complete words at any point inside command in prompt, also use option name
+ as well as command names.
+* Per-client prompt history of up to 100 items.
+* Use a splay tree for key bindings instead of an array. As a side-effect this
+ sorts them when listed.
+
+22 December 2008
+
+* Use the right keys for home and end.
+
+20 December 2008
+
+* Add vim mode for tmux configuration file to examples/, from Tiago Cunha.
+
+15 December 2008
+
+* New command, source-file (alias source), to load a configuration
+ file. Written by Tiago Cunha, many thanks.
+
+13 December 2008
+
+* Work around lack of dch. On Linux, the rxvt termcap doesn't have it (it is
+ lying, but we can't really start disbelieving termcaps...). This is a bit
+ horrible - I can see no way to do it without pretty much redrawing the whole
+ line, but it works...
+
+10 December 2008
+
+* glibc's getopt(3) is useless: it is not POSIX compliant without jumping
+ through non-portable hoops, and the method of resetting it is unclear (the
+ man page on my system says set optind to 1, but other sources say 0). So,
+ import OpenBSD's getopt_long.c into compat/ for use on Linux and use the
+ clearly documented optreset = optind = 1 method. This fixes some strange
+ issues with command parsing (getting the syntax wrong would prevent any
+ further commands being parsed).
+
+06 December 2008
+
+* Bring set/setw/show/showw into line with other commands. This means that by
+ default they now affect the current window (if any); the new -g flag must be
+ passed to set the global options. This changes the behaviour of set/show and
+ WILL BREAK CURRENT CONFIGURATIONS.
+
+ In summary, whether in the configuration file, the command prompt, or a key
+ binding, use -g to set a global option, use -t to specify a particular window
+ or session, or omit both to try and use the current window or session.
+
+ This makes set/show a bit of a pain but is the correct behaviour for
+ setw/showw and is the same as every other command, so we can put up with a
+ bit of pain for consistency.
+* Redo window options. They now work in the same way to session options with a
+ global options set. showw/setw commands now have similar syntax to show/set
+ (including the ability to use abbreviations).
+
+ PLEASE NOTE this includes the following configuration-breaking changes:
+
+ - remain-by-default is now GONE, use "setw -g remain-on-exit" to apply the
+ global window option instead;
+ - mode-keys is now a window option rather than session - use "setw [-g]
+ mode-keys" instead of set.
+
+ There are also some additions:
+
+ - message-fg and message-bg session options to control status line message
+ colours;
+ - mode-fg and mode-bg window options to set colours in window modes such as
+ copy mode.
+
+ The options code still a mess and now there is twice as much of it :-(.
+
+02 December 2008
+
+* Add support for including the window title in status-left or status-right
+ strings by including the character pair "#T". This may be prefixed with
+ a number to specify a maximum length, for example "#24T" to use at most
+ 24 characters of the title.
+* Introduce two new options, status-left-length and status-right-length,
+ control the maximum length of left and right components of the status bar.
+* elinks (and possibly others) bypass the terminal and talk directly to X to
+ restore the window title when exiting. tmux can't know about this particular
+ bit of stupidity so the title ends up strange - the prefix isn't terribly
+ important and elinks is quite useful so just get rid of it.
+
+27 November 2008
+
+* Tweaks to support Dragonfly.
+
+17 November 2008
+
+* tmux 0.5 released.
+
+16 November 2008
+
+* New window option: "utf8"; this must be on (it is off by default) for UTF-8
+ to be parsed. The global/session option "utf8-default" controls the setting
+ for new windows.
+
+ This means that by default tmux does not handle UTF-8. To use UTF-8 by
+ default it is necessary to a) "set utf8-default on" in .tmux.conf b) start
+ tmux with -u on any terminal which support UTF-8.
+
+ It seems a bit unnecessary for this to be a per-window option but that is
+ the easiest way to do it, and it can't do any harm...
+* Enable default colours if op contains \033[39;49m, based on a report from
+ fulvio ciriaco.
+
+12 November 2008
+
+* Keep stack of last windows rather than just most recent; based on a diff from
+ joshe.
+
+04 November 2008
+
+* Don't try to redraw status line when showing a prompt or message; if it does,
+ the status timer is never reset so it redraws on every loop. Spotted by
+ joshe.
+
+09 October 2008
+
+* Translate 256 colours into 16 if 256 is not available, same as screen does.
+* Better support for OSC command (only to set window title now), and also
+ support using APC for the same purpose (some Linux default shell profiles do
+ this).
+
+25 September 2008
+
+* Large internal rewrite to better support 256 colours and UTF-8. Screen data
+ is now stored as single two-way array of structures rather than as multiple
+ separate arrays. Also simplified a lot of code.
+
+ Only external changes are three new flags, -2, -d and -u, which force tmux to
+ assume the terminal supports 256 colours, default colours (useful for
+ xterm-256color which lacks the AX flag), or UTF-8 respectively.
+
+10 September 2008
+
+* Split off colour conversion code from screen code.
+
+09 September 2008
+
+* Initial UTF-8 support. A bit ugly and with a limit of 4096 UTF-8
+ characters per window.
+
+08 September 2008
+
+* 256 colour support. tmux attempts to autodetect the terminal by looking
+ both at what ncurses reports (usually wrong for xterm) and checking if
+ the TERM contains "256col". For xterm TERM=xterm-256color is needed (as
+ well as a build that support 256 colours); this seems to work for rxvt
+ as well. On non-256 colour terminals, high colours are translated to white
+ foreground and black background.
+
+28 August 2008
+
+* Support OS X/Darwin thanks to bsd-poll.c from OpenSSH. Also convert
+ from clock_gettime(2) to gettimeofday(2) as OS X doesn't support the
+ former; microsecond accuracy will have to be sufficient ;-).
+
+07 August 2008
+
+* Lose some unused/useless wrapper functions.
+
+25 July 2008
+
+* Shell variables may now be defined and used in configuration file. Define
+ variables with:
+
+ VAR=1
+
+ And use with:
+
+ renamew ${VAR}
+ renamew "x${VAR}x"
+
+ Also some other fixes to make, for example, "abc""abc" work similarly to
+ the shell.
+
+24 July 2008
+
+* Finally lose inconsistently-used SCREEN_DEF* defines.
+* If cursor mode is on, switch the arrow keys from \033[A to \033OA.
+* Support the numeric keypad in both application and numbers mode. This is
+ different from screen which always keeps it in application mode.
+
+19 July 2008
+
+* Unbreak "set status" - tmux thought it was ambiguous, reported by rivo nurges.
+
+02 July 2008
+
+* Split vi and emacs mode keys into two tables and add an option (mode-keys)
+ to select between them. Default is emacs, use,
+
+ tmux set mode-keys vi
+
+ to change to vi.
+
+ vi mode uses space to start selection, enter to copy selection and escape
+ to clear selection.
+
+01 July 2008
+
+* Protocol versioning. Clients which identify as a different version from the
+ server will be rejected.
+* tmux 0.4 released.
+
+29 June 2008
+
+* Zombie windows. These are not closed when the child process dies. May be
+ set for a window with the new "remain-on-exit" option; the default setting
+ of this flag for new windows may be set with the "remain-by-default" session
+ option.
+
+ A window may be restarted with the respawn-window command:
+
+ respawn-window [-k] [command]
+
+ If -k is given, any existing process running in the window is killed;
+ if command is omitted, the same command as when the window was first
+ created is used.
+
+27 June 2008
+
+* Handle nonexistent session or client to -t properly.
+
+25 June 2008
+
+* select-prompt command to allow a window to be selected at a prompt. Only
+ windows in the current session may be selected. Bound to ' by default.
+ Suggested by merdely.
+* move-window command. Requested by merdely.
+* Support binding alt keys (prefixed with M-). Change default to use
+ C- for ctrl keys (^ is still accepted as an alternative).
+* Slim down default key bindings: support lowercase only.
+* Handle escaped keys properly (parse eg \033b into a single key code) and
+ use this to change copy mode next/previous work to M-f and M-b to match
+ emacs.
+
+24 June 2008
+
+* Next word (C-n/w) and previous word (C-b/b) in copy mode.
+
+23 June 2008
+
+* list-commands command (alias lscm).
+* Split information about options into a table and use it to parse options
+ on input (allowing abbreviations) and to print them with show-options
+ (meaning that bell-action gets a proper string). This turned out a bit ugly
+ though :-/.
+
+22 June 2008
+
+* Do not translate black and white into default if the terminal supports
+ default colours. This was nice to force programs which didn't use default
+ colours to be properly transparent in rxvt/aterm windows with a background
+ image, but it causes trouble if someone redefines the default foreground and
+ background (to have black on white or something).
+
+21 June 2008
+
+* Naive tab completion in the command prompt. This only completes command
+ names if a) they are at the start of the text b) the cursor is at
+ the end of the text c) the text contains no spaces.
+* Only attempt to set the title where TERM looks like an xterm (contains
+ "xterm", "rxvt" or is "screen"). I hate this but I don't see a better way:
+ setting the title actually kills some other terminals pretty much dead.
+* Strip padding out of terminfo(5) strings. Currently the padding is just
+ ignored, this may need to be altered if there are any software terminals
+ out there that actually need it.
+
+20 June 2008
+
+* buffer-limit option to set maximum size of buffer stack. Default is 9.
+* Initial buffer improvements. Each session has a stack of buffers and each
+ buffer command takes a -b option to manipulate items on the stack. If -b
+ is omitted, the top entry is used. The following commands are currently
+ available:
+
+ set-buffer [-b index] [-t target-session] string
+ paste-buffer [-d] [-b index] [-t target-window]
+ delete-buffer [-b index] [-t target-session]
+ show-buffers [-t target-session]
+ show-buffer [-b index] [-t target-session]
+
+ -d to paste-buffer deletes the buffer after pasting it.
+* New option, display-time, sets the time status line messages stay on screen
+ (unless a key is pressed). Set in milliseconds, default is 750 (0.75 seconds).
+ The timer is only checked every 100 ms or so.
+
+19 June 2008
+
+* Use "status" consistently for status line option, and prefix for "prefix" key
+ option.
+* Allow commands to be entered at a prompt. This is triggered with the
+ command-prompt command, bound to : by default.
+* Show status messages properly, without blocking the server.
+
+18 June 2008
+
+* New option, set-titles. On by default, this attempts to set the window title
+ using the \e]2;...\007 xterm code.
+
+ Note that elinks requires the STY environment variable (used by screen) to be
+ set before it will set the window title. So, if you want window titles set by
+ elinks, set STY before running it (any value will do). I can't do this for all
+ windows since setting it to an invalid value breaks screen.
+* Show arrows at either end of status line when scrolled if more windows
+ exist. Highlight the arrow if a hidden window has activity or bell.
+* Scroll the status line to show the current window if necessary. Also handle
+ windows smaller than needed better (show a blank status line instead of
+ hanging or crashing).
+
+17 June 2008
+
+* tmux 0.3 released.
+
+16 June 2008
+
+* Add some information messages when window options are changed, suggested by
+ Mike Erdely. Also add a -q command-line option to suppress them.
+* show-window-options (showw) command.
+
+15 June 2008
+
+* show-options (show) command to show one or all options.
+
+14 June 2008
+
+* New window options: force-width and force-height. This will force a window
+ to an arbitrary width and height (0 for the default unlimited). This is
+ neat for emacs which doesn't have a sensible way to force hard wrapping at 80
+ columns. Also, don't try to be clever and use clr_eol when redrawing the
+ whole screen, it causes trouble since the redraw functions are used to draw
+ the blank areas too.
+* Clear the blank area below windows properly when they are smaller than client,
+ also add an indicator line to show the vertical limit.
+* Don't die on empty strings in config file, reported by Will Maier.
+
+08 June 2008
+
+* Set socket mode +x if any sessions are attached and -x if not.
+
+07 June 2008
+
+* Make status-interval actually changeable.
+
+06 June 2008
+
+* New window option: aggressive-resize. Normally, windows are resized to the
+ size of the smallest attached session to which they are linked. This means a
+ window only changes size when sessions are detached or attached, or they are
+ linked or unlinked from a session. This flag changes a window to be the size
+ of the smallest attached session for which it is the current window - it is
+ resized every time a session changes to it or away from it. This is nice for
+ things that handle SIGWINCH well (like irssi) and bad for things like shells.
+* The server now exits when no sessions remain.
+* Fix bug with inserting characters with TERM=xterm-color.
+
+05 June 2008
+
+* Completely reorganise command parsing. Much more common code in cmd-generic.c
+ and a new way of specifying windows, clients or sessions. Now, most commands
+ take a -t argument, which specifies a client, a session, or a window target.
+ Clients and sessions are given alone (sessions are fnmatch(3)d and
+ clients currently not), windows are give by (client|session):index. For
+ example, if a user is in session "1" window 0 on /dev/ttypi, these should all
+ be equivalent:
+
+ tmux renamew newname (current session and window)
+ tmux renamew -t: newname (current session and window)
+ tmux renamew -t:0 newname (current session, window 0)
+ tmux renamew -t0 newname (current session, window 0)
+ tmux renamew -t1:0 newname (session 1, window 0)
+ tmux renamew -t1: newname (session 1's current window)
+ tmux renamew -t/dev/ttypi newname (client /dev/ttypi's current
+ session and window)
+ tmux renamew -t/dev/ttypi: newname (client /dev/ttypi's current
+ session and window)
+ tmux renamew -t/dev/ttypi:0 newname (client /dev/ttypi's current
+ session, window 0)
+
+ This does have some downsides, for example, having to use -t on selectw,
+
+ tmux selectw -t7
+
+ is annoying. But then using non-flagged arguments would mean renaming the
+ current window would need to be something like:
+
+ tmux renamew : newname
+
+ It might be better not to try and be so consistent; comments to the usual
+ address ;-).
+* Infrastructure for printing arguments in list-keys output. Easy ones only for
+ now.
+
+04 June 2008
+
+* Add some vi(1) key bindings in copy mode, and support binding ^[, ^\, ^]
+ ^^ and ^_. Both from/prompted by Will Maier.
+* setw monitor-activity and set status without arguments now toggle the current
+ value; suggested by merdely.
+* New command set-window-option (alias setw) to set the single current window
+ option: monitor-activity to determine whether window activity is shown in
+ the status bar for that window (default off).
+* Change so active/bell windows are inverted in status line.
+* Activity monitoring - window with activity are marked in status line. No
+ way to disable this/filter windows yet.
+* Brought select-window command into line with everything else; it now uses
+ -i for the window index.
+* Strings to display on the left and right of the status bar may now be set
+ with the status-left and status-right options. These are passed through
+ strftime(3) before being displayed. The status bar is automatically updated
+ at an interval set by the status-interval option. The default is to display
+ nothing on the left and the date and time on the left; the default update
+ interval is 15 seconds.
+
+03 June 2008
+
+* Per session options. Setting options without specifying a session sets the
+ global options as normal (global options are inherited by all sessions);
+ passing -c or -s will set the option only for that session.
+* Because a client has a session attached, any command needing a session can
+ take a client and use its session. So, anything that used to accept -s now
+ accepts -c as well.
+* -s to specify session name now supports fnmatch(3) wildcards; if multiple
+ sessions are found, or if no -s is specified, the most newly created is used.
+* If no command is specified, assume new-session. As a byproduct, clean up
+ command default values into separate init functions.
+* kill-server command.
+
+02 June 2008
+
+* New command, start-server (alias "start"), to start the tmux server and do
+ nothing else. This is good if you have a configuration file which creates
+ windows or sessions (like me): in that case, starting the server the first
+ time tmux new is run is bad since it creates a new session and window (as
+ it is supposed to - starting the server is a side-effect).
+
+ Instead, I have a little script which does the equivalent of:
+
+ tmux has -s0 2>/dev/null || tmux start
+ tmux attach -d -s0
+
+ And I use it to start the server if necessary and attach to my primary
+ session.
+* Basic configuration file in ~/.tmux.conf or specified with -f. This is file
+ contains a set of tmux commands that are run the first time the server is
+ started. The configuration commands are executed before any others, so
+ if you have a configuration file that contains:
+
+ new -d
+ neww -s0
+
+ And you do the following without an existing server running:
+
+ tmux new
+
+ You will end up with two sessions, session 0 with two windows (created by
+ the configuration file) and your client attached to session 1 with one
+ window (created by the command-line command). I'm not completely happy with
+ this, it seems a little non-obvious, but I haven't yet decided what to do
+ about it.
+
+ There is no environment variable handling or other special stuff yet.
+
+ In the future, it might be nice to be able to have per-session configuration
+ settings, probably by having conditionals in the file (so you could, for
+ example, have commands to define a particular window layout that would only
+ be invoked if you called tmux new -smysession and mysession did not already
+ exist).
+* BIG CHANGE: -s and -c to specify session name and client name are now passed
+ after the command rather than before it. So, for example:
+
+ tmux -s0 neww
+
+ Becomes:
+
+ tmux neww -s0
+
+ This is to allow them to be used in the (forthcoming) configuration file
+ THIS WILL BREAK ANY CURRENT SCRIPTS OR ALIASES USING -s OR -c.
+
+01 June 2008
+
+* Bug fix: don't die if -k passed to link-window and the destination doesn't
+ exist.
+* New command, send-keys, will send a set of keys to a window.
+
+31 May 2008
+
+* Fix so tmux doesn't hang if the initial window fails for some reason. This
+ was highlighted by problems on Darwin, thanks to Elias Pipping for the report
+ and access to a test account. (tmux still won't work on Darwin since its
+ poll(2) is broken.)
+
+02 January 2008
+
+* Don't attempt to reset the tty on exit if it has been closed externally.
+
+06 December 2007
+
+* Restore checks for required termcap entries and add a few more obvious
+ emulations.
+* Another major reorganisation, this time of screen handling. A new set of
+ functions, screen_write_*, are now used to write to a screen and a tty
+ simultaneously. These are used by the input parser to update the base
+ window screen and also by the different modes which now interpose their own
+ screen.
+
+30 November 2007
+
+* Support \ek...\e\ to set window name.
+
+27 November 2007
+
+* Enable/disable mouse when asked, if terminal claims to support it. Mouse
+ sequences are just passed through unaltered for the moment.
+* Big internal reorganisation. Rather than leaving control of the tty solely in
+ the client and piping all data through a socket to it, change so that the
+ server opens the tty again and reads and writes to it directly. This avoids
+ a lot of buffering and copying. Also reorganise the redrawing stuff so that
+ everything goes through screen_draw_* - this makes the code simpler, but
+ still needs broken up more, and all the ways of writing to screens should be
+ more consistent.
+
+26 November 2007
+
+* Rather than shifting up one line at a time once the history is full,
+ shift by 10% of the history each time. This is faster.
+* Add ^A and ^E to copy mode to move to start-of-line/end-of-line.
+
+24 November 2007
+
+* Support for alt charset mode (VT100 graphics characters).
+
+23 November 2007
+
+* Mostly complete copy & paste. Copy mode entered with C-b [ (copy-mode
+ command). In copy mode, arrow keys/page up/page down/hjkl/C-u/C-f navigate,
+ space or C-space starts selection, and enter or C-w copies and (important!)
+ exits copy mode. C-b ] (paste-buffer) pastes into current window. No
+ extra utility keys (bol/eol/clear selection/etc), only one single buffer,
+ and no buffer manipulation commands (clear/view/etc) yet. The code is also
+ fugly :-(.
+* history-limit option to set maximum history. Does not apply retroactively to
+ existing windows! Lines take up a variable amount of space, but a reasonable
+ guess for an 80-column terminal is 250 KB per 1000 lines (of history used,
+ an empty history takes no space).
+
+21 November 2007
+
+* Create every line as zero length and only expand it as data is written,
+ rather than creating at full size immediately.
+* Make command output (eg list-keys) go to a scrollable window similar to
+ scroll mode.
+* Redo screen redrawing so it is a) readable b) split into utility functions
+ that can be used outside screen.c. Use these to make scroll mode only
+ redraw what it has to which gets rid of irritating flickering status box and
+ makes it much faster.
+* Full line width memory and horizontal scrolling in history.
+* Initial support for scroll history. = to enter scrolling mode, and then
+ vi keys or up/down/pgup/pgdown to navigate. Q to exit. No horizontal history
+ yet (need per-line sizes) and a few kinks to be worked out (resizing while in
+ history mode will probably cause trouble).
+
+20 November 2007
+
+* Fix format string error with "must specify a client" message. Also
+ sprinkle some printflike tags.
+* tmux 0.1 released.
+
+17 November 2007
+
+* (nicm) Add -k option to link-window to kill target window if it exists.
+
+16 November 2007
+
+* (nicm) Split in-client display into two columns. This is a hack but not a lot
+ more so than that bit is already and it helps with lots of keys.
+* (nicm) switch-client command to switch client between different sessions. This
+ is pretty cool:
+
+ $ tmux bind q switch 0
+ $ tmux bind w switch 1
+
+ Then you can switch between sessions 0 and 1 with a key :-).
+* (nicm) Accept "-c client-tty" on command line to allow client manipulation
+ commands, and change detach-/refresh-session to detach-/refresh-client (this
+ loses the -a behaviour, but at some point -session versions may return, and
+ -c will allow fnmatch(3)).
+* (nicm) List available commands on ambiguous command.
+
+12 November 2007
+
+* (nicm) If the terminal supports default colours (AX present), force black
+ background and white foreground to default. This is useful on transparent
+ *terms for programs which don't do it themselves (like most(1)).
+* (nicm) Fill in the rest of the man page.
+* (nicm) kill-session command.
+
+09 November 2007
+
+* (nicm) C-space is now "^ " not "^@".
+* (nicm) Support tab (\011).
+* (nicm) Initial man page outline.
+* (nicm) -V to show version.
+* (nicm) rename-session command.
+
+08 November 2007
+
+* (nicm) Check for required terminal capabilities on start.
+
+31 October 2007
+
+* (nicm) Linux port.
+
+30 October 2007
+
+* (nicm) swap-window command. Same as link-window but swaps windows.
+
+26 October 2007
+
+* (nicm) Saving scroll region on \e7 causes problems with ncmpc so I guess
+ it is not required.
+* (nicm) unlink-window command.
+* (nicm) link-window command to link an existing window into another session
+ (or another index in the same session). Syntax:
+
+ tmux -s dstname link-window [-i dstidx] srcname srcidx
+
+* (nicm) Redo window data structures. The global array remains, but each per-
+ session list is now a RB tree of winlink structures. This disassociates the
+ window index from the array size (allowing arbitrary indexes) which still
+ allowing windows to have multiple indexes.
+
+25 October 2007
+
+* (nicm) has-session command: checks if session exists.
+
+24 October 2007
+
+* (nicm) Support for \e6n to request cursor position. resize(1) now works.
+* (nicm) Support for \e7, \e8 save/restore cursor and attribute sequences.
+ Currently don't save mode (probably should). Also change some cases where
+ out-of-bound values are ignored to limit them to within range (there are
+ others than need to be checked too).
+
+23 October 2007
+
+* (nicm) Lift limit on session name passed with -s.
+* (nicm) Show size in session/window lists.
+* (nicm) Pass tty up to server when client identifies and add a list-clients
+ command to list connected clients.
+
+20 October 2007
+
+* (nicm) Add default-command option and change default to be $SHELL rather than
+ $SHELL -l. Also try to read shell from passwd db if $SHELL isn't present.
+
+19 October 2007
+
+* (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 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,
+ the status bar always reflects any bells.
+* (nicm) Refresh session command.
+
+12 October 2007
+
+* (nicm) Add a warning if $TMUX exists on new/attach.
+* (nicm) send-prefix command. Bound to C-b by default.
+* (nicm) set status, status-fg, status-bg commands. fg and bg are as a number
+ from 0 to 8 or a string ("red", "blue", etc). status may be 1/0, on/off,
+ yes/no.
+* (nicm) Make status line mark window in yellow on bell.
+
+04 October 2007
+
+* (nicm) -d option to attach to detach all other clients on the same session.
+* (nicm) Partial resizing support. Still buggy. A C-b S and back sometimes fixes
+ it when it goes wonky.
+* (mxey) Added my tmux start script as an example (examples/start-tmux.sh).
+* (mxey) New sessions can now be given a command for their first window.
+* (mxey) Fixed usage statement for new-window.
+* (nicm) attach-session (can't believe I forgot it until now!) and list-windows
+ commands.
+* (nicm) rename-window and select-window commands.
+* (nicm) set-option command (alias set): "tmux set-option prefix ^A".
+* (nicm) Key binding and unbinding is back.
+
+03 October 2007
+
+* (nicm) {new,next,last,previous}-window.
+* (nicm) Rewrite command handling so commands are much more generic and the
+ same commands are used for command line and keys (although most will probably
+ need to check how they are called). Currently incomplete (only new/detach/ls
+ implemented). Change: -s is now passed before command again!
+* (nicm) String number arguments. So you can do: tmux bind ^Q create "blah".
+* (nicm) Key binding. tmux bind key command [argument] and tmux unbind key.
+ Key names are in a table in key-string.c, plus A is A, ^A is ctrl-A.
+ Possible commands are in cmd.c (look at cmd_bind_table).
+* (nicm) Move command parsing into the client. Also rename some messages and
+ tidy up a few bits. Lots more tidying up needed :-/.
+
+02 October 2007
+
+* (nicm) Redraw client status lines on rename.
+* (nicm) Error on ambiguous command.
+
+01 October 2007
+
+* (nicm) Restore window title handling.
+* (nicm) Simple uncustomisable status line with window list.
+
+30 September 2007
+
+* (nicm) Window info command for debugging, C-b I.
+
+29 September 2007
+
+* (nicm) Deleting/inserting lines should follow scrolling region. Fix.
+* (nicm) Allow creation of detached sessions: "tmux new-session -d".
+* (nicm) Permit error messages to be passed back for transient clients like
+ rename. Also make rename -i work.
+* (nicm) Pass through bell in any window to current.
+
+28 September 2007
+
+* (nicm) Major rewrite of input parser:
+ - Lose the old weirdness in favour of a state machine.
+ - Merge in parsing from screen.c.
+ - Split key parsing off into a separate file.
+ This is step one towards hopefully allowing a status line. It requires
+ that we output data as if the terminal had one line less than it really does -
+ a serious problem when it comes to things like scrolling. This change
+ consolidates all the range checking and limiting together which should make
+ it easier.
+* (mxey) Added window renaming, like "tmux rename [-s session] [-i index] name"
+
+27 September 2007
+
+* Split "tmux list" into "tmux list-sessions" (ls) and "list-windows" (lsw).
+* New command session selection:
+ - if name is specified, look for it and use it if it exists, otherwise
+ error
+ - if no name specified, try the current session from $TMUX
+ - if $TMUX doesn't exist, and there is only one session, use it,
+ otherwise error
+
+26 September 2007
+
+* Add command aliases, so "ls" is an alias for "list".
+* Rename some commands and alter syntax to take options after a la CVS. Also
+ change some flags. So:
+
+ tmux -s/socket -nabc new
+
+ Becomes:
+
+ tmux -S/socket new -sabc
+
+* Major tidy and split of client/server code.
+
+22 September 2007
+
+* Window list command (C-b W). Started by Maximilian Gass, finished by me.
+
+20 September 2007
+
+* Specify meta via environment variable (META).
+* Record last window and ^L key to switch to it. Largely from Maximilian Gass.
+* Reset ignored signals in child after forkpty, makes ^C work.
+* Wrap on next/previous. From Maximilian Gass.
+
+19 September 2007
+
+* Don't renumber windows on close.
+
+28 August 2007
+
+* Scrolling region (\e[r) support.
+
+27 August 2007
+
+* Change screen.c to work more logically and hopefully fix heap corruption.
+
+09 July 2007
+
+* Initial import to CVS. Basic functions are working, albeit with a couple of
+ showstopper memory bugs and many missing features. Detaching, reattaching,
+ creating new sessions, listing sessions work acceptably for using with shells.
+ Simple curses programs (top, systat, tetris) and more complicated ones (mutt,
+ emacs) that don't require scrolling regions (ESC[r) mostly work fine
+ (including mutt, emacs). No status bar yet and no key remapping or other
+ customisation.
+
+$Id$
+
+ LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
+ LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms
+ LocalWords: dstidx srcname srcidx winlink lsw nabc sabc Exp Tiago Cunha dch
+ LocalWords: setw Chisnall renamew merdely eg Maier newname selectw neww Gass
diff --git a/FAQ b/FAQ
new file mode 100644
index 00000000..41b917c8
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,400 @@
+tmux frequently asked questions
+
+******************************************************************************
+* PLEASE NOTE: most display problems are due to incorrect TERM! Before *
+* reporting problems make SURE that TERM settings are correct inside and *
+* outside tmux. *
+* *
+* Inside tmux TERM must be "screen" or similar (such as "screen-256color"). *
+* Don't bother reporting problems where it isn't! *
+* *
+* Outside, it must match your terminal: particularly, use "rxvt" for rxvt *
+* and derivatives. *
+******************************************************************************
+
+* How is tmux different from GNU screen?
+
+tmux and GNU screen have many similarities. Some of the main differences I am
+aware of are (bearing in mind I haven't used screen for a few years now):
+
+- tmux uses a client-server model. Each server has single Unix domain socket in
+ /tmp and within one server there are multiple sessions which may be attached
+ to multiple clients (terminals).
+
+ This has advantages, notably: windows may be linked simultaneously to
+ multiple sessions; windows may be moved freely between sessions; and a client
+ may be switched between sessions easily (C-b D). There is one major
+ disadvantage: if the server crashes, game over, all sessions die. In
+ practice, however, tmux is quite stable and gets more so as people report any
+ bugs they hit :-).
+
+ This model is different from screen, where typically each new screen instance
+ is independent. tmux supports the same behaviour by using multiple servers
+ with the -L option but it is not typically recommended.
+
+- Different command interfaces. One of the goals of tmux is that the shell
+ should be easily usable as a scripting language - almost all tmux commands
+ can be used from the shell and behave identically whether used from the
+ shell, from a key binding or from the command prompt. Personally I also find
+ tmux's command interface much more consistent and clearer, but this is
+ subjective.
+
+- tmux calls window names (what you see in the status line) "names", screen
+ calls them "titles".
+
+- tmux has a multiple paste buffers. Not a major one but comes in handy quite a
+ lot.
+
+- tmux supports automatically renaming windows to the running application
+ without gross hacks using escape sequences. Its even on by default.
+
+- tmux has a choice of vi or emacs key layouts. Again, not major, but I use
+ emacs so if tmux did support only one key set it would be emacs and then all
+ the vi users would get humpy. Key bindings may be completely reconfigured in
+ any case.
+
+- tmux has an option to limit the window size.
+
+- tmux has search in windows (C-b f).
+
+- The window split (pane) model is different. tmux has two objects, windows and
+ panes; screen has just windows. This difference has several implications:
+
+ * In screen you can have a window appear in several layouts, in tmux a pane
+ can only be in one window (fixing this is a big todo item but quite
+ invasive).
+
+ * tmux layouts are immutable and do not get changed unless you modify them.
+
+ * In tmux, all panes are closed when you kill a window.
+
+ * tmux panes do not have individual names, titles and so on.
+
+ I think tmux's model is much easier to manage and navigate within a window,
+ but breaking panes off from and joining them to windows is more clumsy.
+
+ tmux also has support for preset pane layouts.
+
+- tmux's status line syntax is more readable and easier to use. I think it'd be
+ hard for anyone to argue with this. tmux doesn't support running a command
+ constantly and always using the last line of its output, commands must be run
+ again each time.
+
+- tmux has modern, easily extended code. Again hard to argue screen is better
+ if you have looked at the code.
+
+- tmux depends on libevent. I don't see this as a disadvantage: libevent is
+ small and portable, and on modern systems with current package management
+ systems dependencies are not an issue. libevent brings advantages in code
+ simplicity and performance.
+
+- screen allows the window to be bigger than the terminal and can pan around
+ it. tmux limits the size to the largest attached client. This is a big todo
+ item for tmux but it is not trivial.
+
+- screen has builtin serial and telnet support; this is bloat and is unlikely
+ to be added to tmux.
+
+- screen has support for updating utmp. Nobody has really come up with a clean,
+ portable way to do this without making tmux setuid or setgid yet.
+
+- Environment handling is different.
+
+- tmux tends to be more demanding on the terminal so tends to show up terminal
+ and application bugs which screen does not.
+
+- screen has wider platform support, for example IRIX, and for odd terminals.
+
+* I found a bug! What do I do?
+
+Please send bug reports by email to nicm@users.sourceforge.net or
+tmux-users@lists.sourceforge.net. Please include as much of the following
+information as possible:
+
+- the version of tmux you are running;
+- the operating system you are using and its version;
+- the terminal emulator you are using and the TERM setting when tmux was
+ started;
+- a description of the problem;
+- if the problem is repeatable, the steps to repeat the problem;
+- for screen corruption issues, a screenshot and the output of "infocmp $TERM"
+ from outside tmux are often very useful.
+
+* Why doesn't tmux do $x?
+
+Please send feature requests by email to nicm@users.sourceforge.net.
+
+* Why do you use the screen terminal description inside tmux? It sucks.
+
+It is already widely available. It is planned to change to something else such
+as xterm-xfree86 at some point, if possible.
+
+* I don't see any colour in my terminal! Help!
+
+On some platforms, common terminal descriptions such as xterm do not include
+colour. screen ignores this, tmux does not. If the terminal emulator in use
+supports colour, use a value for TERM which correctly lists this, such as
+xterm-color.
+
+* tmux freezes my terminal when I attach to a session. I even have to kill -9
+ the shell it was started from to recover!
+
+Some consoles really really don't like attempts to set the window title. Tell
+tmux not to do this by turning off the "set-titles" option (you can do this
+in .tmux.conf):
+
+ set -g set-titles off
+
+If this doesn't fix it, send a bug report.
+
+* Why is C-b the prefix key? How do I change it?
+
+The default key is C-b because the prototype of tmux was originally developed
+inside screen and C-b was chosen not to clash with the screen meta key. It
+also has the advantage of not interfering with the use of C-a for start-of-line
+in emacs and the shell (although it does interfere with previous-character).
+
+Changing is simple: change the "prefix-key" option, and - if required - move
+the binding of the "send-prefix" command from C-b (C-b C-b sends C-b by
+default) to the new key. For example:
+
+ set -g prefix C-a
+ unbind C-b
+ bind C-a send-prefix
+
+* How do I use UTF-8?
+
+When running tmux in a UTF-8 capable terminal, UTF-8 must be turned on in tmux;
+as of release 0.9, tmux attempts to autodetect a UTF-8-capable terminal by
+checking the LC_ALL, LC_CTYPE and LANG environment variables. list-clients may
+be used to check if this is detected correctly; if not, the -u command-line
+flag may be specified when creating or attaching a client to a tmux session:
+
+ $ tmux -u new
+
+Since the 1.0 release, tmux will turn on UTF-8 related options automatically
+(ie status-utf8, and utf8) if the above conditions are met.
+
+* How do I use a 256 colour terminal?
+
+Provided the underlying terminal supports 256 colours, it is usually sufficient
+to add the following to ~/.tmux.conf:
+
+ set -g default-terminal "screen-256color"
+
+Note that some platforms do not support "screen-256color" ("infocmp
+screen-256color" will return an error) - in this case see the next entry in
+this FAQ.
+
+tmux attempts to detect a 256 colour terminal both by looking at the colors
+terminfo entry and by looking for the string "256col" in the TERM environment
+variable.
+
+If both these methods fail, the -2 flag may be passed to tmux when attaching
+to a session to indicate the terminal supports 256 colours.
+
+* vim or $otherprogram doesn't display 256 colours. What's up?
+
+Some programs attempt to detect the number of colours a terminal is capable of
+by checking the colors terminfo or Co termcap entry. However, this is not
+reliable, and in any case is missing from the "screen" terminal description
+used inside tmux.
+
+There are two options (aside from using "screen-256color") to allow programs to
+recognise they are running on a 256-colour terminal inside tmux:
+
+- Manually force the application to use 256 colours always or if TERM is set to
+ screen. For vim, you can do this by overriding the t_Co option, see
+ http://vim.wikia.com/wiki/256_colors_in_vim.
+- Creating a custom terminfo file that includes colors#256 in ~/.terminfo and
+ using it instead. These may be compiled with tic(1).
+
+* How do I make Ctrl-PgUp and Ctrl-PgDn work in vim?
+
+tmux supports passing through ctrl (and where supported by the client terminal,
+alt and shift) modifiers to function keys using xterm(1)-style key sequences.
+This may be enabled per window, or globally with the tmux command:
+
+ setw -g xterm-keys on
+
+Because the TERM variable inside tmux must be set to "screen", vim will not
+automatically detect these keys are available; however, the appropriate key
+sequences can be overridden in .vimrc using the following:
+
+ if &term == "screen"
+ set t_kN=^[[6;*~
+ set t_kP=^[[5;*~
+ endif
+
+And similarly for any other keys for which modifiers are desired.
+
+Please note that the "xterm-keys" setting may affect other programs, in the
+same way as running them in a standard xterm; for example most shells do not
+expect to receive xterm(1)-style key sequences so this setting may prevent keys
+such as ctrl-left and ctrl-right working correctly. tmux also passes through
+the ctrl (bit 5 set, for example ^[[5~ to ^[[5^) modifier in non-xterm(1) mode;
+it may be possible to configure vim to accept these, an example of how to do so
+would be welcome.
+
+vim users may also want to set the "ttyfast" option inside tmux.
+
+* Why doesn't elinks set the window title inside tmux?
+
+There isn't a way to detect if a terminal supports setting the window title, so
+elinks attempts to guess by looking at the environment. Rather than looking for
+TERM=screen, it uses the STY variable to detect if it is running in screen;
+tmux does not use this so the check fails. A workaround is to set STY before
+running elinks.
+
+The following shell function does this, and also clears the window title on
+exit (elinks, for some strange reason, sets it to the value of TERM):
+
+ elinks() {
+ STY= `which elinks` $*
+ echo -ne \\033]0\;\\007;
+ }
+
+* What is the proper way to escape characters with #(command)?
+
+When using the #(command) construction to include the output from a command in
+the status line, the command will be parsed twice. First, when it's read by the
+configuration file or the command-prompt parser, and second when the status
+line is being drawn and the command is passed to the shell. For example, to
+echo the string "(test)" to the status line, either single or double quotes
+could be used:
+
+ set -g status-right "#(echo \\\\(test\\\\))"
+ set -g status-right '#(echo \\\(test\\\))'
+
+In both cases, the status-right option will be set to the string "#(echo
+\\(test\\))" and the command executed will be "echo \(test\)".
+
+* tmux uses too much CPU. What do I do?
+
+Automatic window renaming may use a lot of CPU, particularly on slow computers:
+if this is a problem, turn it off with "setw -g automatic-rename off". If this
+doesn't fix it, please report the problem.
+
+* I use PuTTY and my tmux window pane separators are all qqqqqqqqq's!
+
+PuTTY is using a character set translation that doesn't support ACS line
+drawing. With a Unicode font, try setting PuTTY to use a different translation
+on the Window -> Translation configuration page. For example, change UTF-8 to
+ISO-8859-1 or CP437. It may also be necessary to adjust the way PuTTY treats
+line drawing characters in the lower part of the same configuration page.
+
+* What is the best way to display the load average? Why no #L?
+
+It isn't possible to get the load average portably in code and it is preferable
+not to add portability goop. The following works on at least Linux, *BSD and OS
+X:
+
+uptime|awk '{split(substr($0, index($0, "load")), a, ":"); print a[2]}'
+
+* How do I attach the same session to multiple clients but with a different
+ current window, like screen -x?
+
+One or more of the windows can be linked into multiple sessions manually with
+link-window, or a grouped session with all the windows can be created with
+new-session -t.
+
+* Ctrl and arrow keys doesn't work in putty! What do I do?
+
+putty inverts the sense of the cursor key mode on ctrl, which is a bit hard for
+tmux to detect properly. To get ctrl keys right, change the terminfo settings
+so kUP5 (Ctrl-Up etc) are the adjusted versions, and disable smkx/rmkx so tmux
+doesn't change the mode. For example with this line in .tmux.conf (assuming you
+have TERM set to xterm):
+
+set -g terminal-overrides "xterm*:kLFT5=\eOD:kRIT5=\eOC:kUP5=\eOA:kDN5=\eOB:smkx@:rmkx@"
+
+Note that this will only work in tmux 1.2 and above.
+
+* How can I blank the tmux window?
+
+GNU screen has a feature whereby it will blank the screen after a period of
+inactivity. To do the same thing in tmux, use the lock-command setting, for
+example (with GNU bash):
+
+set -g lock-command 'tput civis && read -s -n1'
+
+This will remove the cursor and tell the shell to quit once a key has been
+pressed. For zsh, use "read -s -k1".
+
+In addition, it's possible to have both blanking and locking (for instance via
+lock(1) or vlock(1)) by using the following:
+
+bind x set lock-command '/usr/bin/vlock' \; lock-client \; set lock-command 'tput civis && read -s -n1'
+
+* vim displays reverse video instead of italics, while less displays italics
+ (or just regular text) instead of reverse. What's wrong?
+
+Screen's terminfo description lacks italics mode and has standout mode in its
+place, but using the same escape sequence that urxvt uses for italics. This
+means applications (like vim) looking for italics will not find it and might
+turn to reverse in its place, while applications (like less) asking for
+standout will end up with italics instead of reverse. To make applications
+aware that tmux supports italics and to use a proper escape sequence for
+standout, you'll need to create a new terminfo file with modified sgr, smso,
+rmso, sitm and ritm entries:
+
+ $ mkdir $HOME/.terminfo/
+ $ screen_terminfo="screen"
+ $ infocmp "$screen_terminfo" | sed \
+ -e 's/^screen[^|]*|[^,]*,/screen-it|screen with italics support,/' \
+ -e 's/%?%p1%t;3%/%?%p1%t;7%/' \
+ -e 's/smso=[^,]*,/smso=\\E[7m,/' \
+ -e 's/rmso=[^,]*,/rmso=\\E[27m,/' \
+ -e '$s/$/ sitm=\\E[3m, ritm=\\E[23m,/' > /tmp/screen.terminfo
+ $ tic /tmp/screen.terminfo
+
+And tell tmux to use it in ~/.tmux.conf:
+
+ set -g default-terminal "screen-it"
+
+If your terminal supports 256 colors, use:
+
+ $ screen_terminfo="screen-256color"
+
+instead of "screen". See the FAQ entry about 256 colors support for more info.
+Also note that tmux will still display reverse video on terminals that do not
+support italics.
+
+If your urxvt cannot display italics at all, make sure you have an italics
+capable font enabled, for example, add to ~/.Xdefaults:
+
+ urxvt.italicFont: xft:Bitstream Vera Sans Mono:italic:autohint=true
+
+* How can I make tmux use my terminal's scrollback buffer?
+
+Normally, tmux enables the terminal's "alternate screen". Most terminals (such
+as xterm) do not save scrollback for the alternate screen. You might prefer
+tmux to use the normal screen, so it uses your terminal's scrollback
+buffer. This way, you can access the scrollback buffer as usual, for example
+using the mouse wheel - although there is no guarantee output inside tmux will
+always (or ever) be added to the scrollback.
+
+You can make tmux use the normal screen by telling it that your terminal does
+not have an alternate screen. Put the following in ~/.tmux.conf:
+
+ set -g terminal-overrides 'xterm*:smcup@:rmcup@'
+
+Adjust if your $TERM does not start with xterm.
+
+tmux will still emulate the alternate screen for applications run under tmux,
+so you don't really lose anything with this setting. The only disadvantage is
+that when you exit tmux, it will not restore whatever was there before you
+started.
+
+* How do I see the default configuration?
+
+Show the default session options by starting a new tmux server with no
+configuration file:
+
+ $ tmux -Lfoo -f/dev/null start\; show -g
+
+Or the default window options:
+
+ $ tmux -Lfoo -f/dev/null start\; show -gw
+
+$Id$
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 9fa55d9b..00000000
--- a/Makefile
+++ /dev/null
@@ -1,139 +0,0 @@
-# $OpenBSD$
-
-PROG= tmux
-SRCS= arguments.c \
- attributes.c \
- cfg.c \
- client.c \
- clock.c \
- cmd-attach-session.c \
- cmd-bind-key.c \
- cmd-break-pane.c \
- cmd-capture-pane.c \
- cmd-choose-buffer.c \
- cmd-choose-client.c \
- cmd-choose-list.c \
- cmd-choose-tree.c \
- cmd-clear-history.c \
- cmd-clock-mode.c \
- cmd-command-prompt.c \
- cmd-confirm-before.c \
- cmd-copy-mode.c \
- cmd-delete-buffer.c \
- cmd-detach-client.c \
- cmd-display-message.c \
- cmd-display-panes.c \
- cmd-find-window.c \
- cmd-has-session.c \
- cmd-if-shell.c \
- cmd-join-pane.c \
- cmd-kill-pane.c \
- cmd-kill-server.c \
- cmd-kill-session.c \
- cmd-kill-window.c \
- cmd-link-window.c \
- cmd-list-buffers.c \
- cmd-list-clients.c \
- cmd-list-commands.c \
- cmd-list-keys.c \
- cmd-list-panes.c \
- cmd-list-sessions.c \
- cmd-list-windows.c \
- cmd-list.c \
- cmd-load-buffer.c \
- cmd-lock-server.c \
- cmd-move-window.c \
- cmd-new-session.c \
- cmd-new-window.c \
- cmd-paste-buffer.c \
- cmd-pipe-pane.c \
- cmd-refresh-client.c \
- cmd-rename-session.c \
- cmd-rename-window.c \
- cmd-resize-pane.c \
- cmd-respawn-pane.c \
- cmd-respawn-window.c \
- cmd-rotate-window.c \
- cmd-run-shell.c \
- cmd-save-buffer.c \
- cmd-select-layout.c \
- cmd-select-pane.c \
- cmd-select-window.c \
- cmd-send-keys.c \
- cmd-server-info.c \
- cmd-set-buffer.c \
- cmd-set-environment.c \
- cmd-set-option.c \
- cmd-show-environment.c \
- cmd-show-messages.c \
- cmd-show-options.c \
- cmd-source-file.c \
- cmd-split-window.c \
- cmd-start-server.c \
- cmd-string.c \
- cmd-suspend-client.c \
- cmd-swap-pane.c \
- cmd-swap-window.c \
- cmd-switch-client.c \
- cmd-unbind-key.c \
- cmd-unlink-window.c \
- cmd-wait-for.c \
- cmd.c \
- cmd-queue.c \
- colour.c \
- control.c \
- control-notify.c \
- environ.c \
- format.c \
- grid-cell.c \
- grid-view.c \
- grid.c \
- input-keys.c \
- input.c \
- job.c \
- key-bindings.c \
- key-string.c \
- layout-custom.c \
- layout-set.c \
- layout.c \
- log.c \
- mode-key.c \
- names.c \
- notify.c \
- options-table.c \
- options.c \
- paste.c \
- procname.c \
- resize.c \
- screen-redraw.c \
- screen-write.c \
- screen.c \
- server-client.c \
- server-fn.c \
- server-window.c \
- server.c \
- session.c \
- signal.c \
- status.c \
- tmux.c \
- tty-acs.c \
- tty-keys.c \
- tty-term.c \
- tty.c \
- utf8.c \
- window-choose.c \
- window-clock.c \
- window-copy.c \
- window.c \
- xmalloc.c \
- xterm-keys.c
-
-CDIAGFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
-CDIAGFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
-CDIAGFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
-CDIAGFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
-
-LDADD= -lutil -lcurses -levent
-DPADD= ${LIBUTIL} ${LIBCURSES} ${LIBEVENT}
-
-.include <bsd.prog.mk>
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 00000000..2ce54b1a
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,248 @@
+# $Id$
+
+# Obvious program stuff.
+bin_PROGRAMS = tmux
+dist_man1_MANS = tmux.1
+
+# Distribution tarball options.
+EXTRA_DIST = \
+ CHANGES FAQ README TODO examples compat \
+ array.h compat.h tmux.h osdep-*.c
+dist-hook:
+ grep "^#found_debug=" configure
+ find $(distdir) -name .svn -type d|xargs rm -Rf
+
+# Preprocessor flags.
+CPPFLAGS += @XOPEN_DEFINES@
+
+# glibc as usual does things ass-backwards and hides useful things by default,
+# so everyone has to add this.
+if IS_GLIBC
+CFLAGS += -D_GNU_SOURCE
+endif
+
+# Set flags for gcc. gcc4 whines abouts silly stuff so it needs slightly
+# different flags.
+if IS_GCC
+CFLAGS += -std=gnu99
+if IS_DEBUG
+CFLAGS += -O0 -g
+CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
+CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
+CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
+CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
+CFLAGS += -Wdeclaration-after-statement
+CPPFLAGS += -DDEBUG
+else
+CFLAGS += -O2
+endif
+if IS_GCC4
+CPPFLAGS += -iquote. -I/usr/local/include
+if IS_DEBUG
+CFLAGS += -Wno-pointer-sign
+endif
+else
+CPPFLAGS += -I. -I- -I/usr/local/include
+endif
+endif
+
+# Set flags for Solaris.
+if IS_SUNOS
+CPPFLAGS += -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
+endif
+
+# Set flags for Sun CC.
+if IS_SUNCC
+CFLAGS += -erroff=E_EMPTY_DECLARATION
+endif
+
+# List of sources.
+dist_tmux_SOURCES = \
+ arguments.c \
+ attributes.c \
+ cfg.c \
+ client.c \
+ clock.c \
+ cmd-attach-session.c \
+ cmd-bind-key.c \
+ cmd-break-pane.c \
+ cmd-capture-pane.c \
+ cmd-choose-buffer.c \
+ cmd-choose-client.c \
+ cmd-choose-list.c \
+ cmd-choose-tree.c \
+ cmd-clear-history.c \
+ cmd-clock-mode.c \
+ cmd-command-prompt.c \
+ cmd-confirm-before.c \
+ cmd-copy-mode.c \
+ cmd-delete-buffer.c \
+ cmd-detach-client.c \
+ cmd-display-message.c \
+ cmd-display-panes.c \
+ cmd-find-window.c \
+ cmd-has-session.c \
+ cmd-if-shell.c \
+ cmd-join-pane.c \
+ cmd-kill-pane.c \
+ cmd-kill-server.c \
+ cmd-kill-session.c \
+ cmd-kill-window.c \
+ cmd-link-window.c \
+ cmd-list-buffers.c \
+ cmd-list-clients.c \
+ cmd-list-commands.c \
+ cmd-list-keys.c \
+ cmd-list-panes.c \
+ cmd-list-sessions.c \
+ cmd-list-windows.c \
+ cmd-list.c \
+ cmd-load-buffer.c \
+ cmd-lock-server.c \
+ cmd-move-window.c \
+ cmd-new-session.c \
+ cmd-new-window.c \
+ cmd-paste-buffer.c \
+ cmd-pipe-pane.c \
+ cmd-queue.c \
+ cmd-refresh-client.c \
+ cmd-rename-session.c \
+ cmd-rename-window.c \
+ cmd-resize-pane.c \
+ cmd-respawn-pane.c \
+ cmd-respawn-window.c \
+ cmd-rotate-window.c \
+ cmd-run-shell.c \
+ cmd-save-buffer.c \
+ cmd-select-layout.c \
+ cmd-select-pane.c \
+ cmd-select-window.c \
+ cmd-send-keys.c \
+ cmd-server-info.c \
+ cmd-set-buffer.c \
+ cmd-set-environment.c \
+ cmd-set-option.c \
+ cmd-show-environment.c \
+ cmd-show-messages.c \
+ cmd-show-options.c \
+ cmd-source-file.c \
+ cmd-split-window.c \
+ cmd-start-server.c \
+ cmd-string.c \
+ cmd-suspend-client.c \
+ cmd-swap-pane.c \
+ cmd-swap-window.c \
+ cmd-switch-client.c \
+ cmd-unbind-key.c \
+ cmd-unlink-window.c \
+ cmd-wait-for.c \
+ cmd.c \
+ colour.c \
+ control.c \
+ control-notify.c \
+ environ.c \
+ format.c \
+ grid-cell.c \
+ grid-view.c \
+ grid.c \
+ input-keys.c \
+ input.c \
+ job.c \
+ key-bindings.c \
+ key-string.c \
+ layout-custom.c \
+ layout-set.c \
+ layout.c \
+ log.c \
+ mode-key.c \
+ names.c \
+ notify.c \
+ options-table.c \
+ options.c \
+ paste.c \
+ resize.c \
+ screen-redraw.c \
+ screen-write.c \
+ screen.c \
+ server-client.c \
+ server-fn.c \
+ server-window.c \
+ server.c \
+ session.c \
+ signal.c \
+ status.c \
+ tmux.c \
+ tty-acs.c \
+ tty-keys.c \
+ tty-term.c \
+ tty.c \
+ utf8.c \
+ window-choose.c \
+ window-clock.c \
+ window-copy.c \
+ window.c \
+ xmalloc.c \
+ xterm-keys.c
+nodist_tmux_SOURCES = osdep-@PLATFORM@.c
+
+# Pile in all the compat/ stuff that is needed.
+if NO_FORKPTY
+nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
+endif
+if NO_IMSG
+nodist_tmux_SOURCES += compat/imsg.c compat/imsg-buffer.c
+endif
+if NO_CLOSEFROM
+nodist_tmux_SOURCES += compat/closefrom.c
+endif
+if NO_DAEMON
+nodist_tmux_SOURCES += compat/daemon.c
+endif
+if NO_SETENV
+nodist_tmux_SOURCES += compat/setenv.c
+endif
+if NO_STRLCAT
+nodist_tmux_SOURCES += compat/strlcat.c
+endif
+if NO_STRLCPY
+nodist_tmux_SOURCES += compat/strlcpy.c
+endif
+if NO_ASPRINTF
+nodist_tmux_SOURCES += compat/asprintf.c
+endif
+if NO_FGETLN
+nodist_tmux_SOURCES += compat/fgetln.c
+endif
+if NO_GETOPT
+nodist_tmux_SOURCES += compat/getopt.c
+endif
+if NO_STRCASESTR
+nodist_tmux_SOURCES += compat/strcasestr.c
+endif
+if NO_STRSEP
+nodist_tmux_SOURCES += compat/strsep.c
+endif
+if NO_VIS
+nodist_tmux_SOURCES += compat/vis.c compat/unvis.c
+endif
+if NO_STRTONUM
+nodist_tmux_SOURCES += compat/strtonum.c
+endif
+if NO_B64_NTOP
+nodist_tmux_SOURCES += compat/b64_ntop.c
+endif
+
+# Update SF web site.
+upload-index.html: update-index.html
+ scp www/index.html www/main.css www/images/*.png \
+ ${USER},tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
+ rm -f www/index.html www/images/small-*
+
+update-index.html:
+ (cd www/images && \
+ rm -f small-* && \
+ for i in *.png; do \
+ convert "$$i" -resize 200x150 "small-$$i"; \
+ done \
+ )
+ sed "s/%%VERSION%%/${VERSION}/g" www/index.html.in >www/index.html
diff --git a/README b/README
new file mode 100644
index 00000000..77c6058d
--- /dev/null
+++ b/README
@@ -0,0 +1,60 @@
+Welcome to tmux!
+
+tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
+to be accessed and controlled from a single terminal. tmux is intended to be a
+simple, modern, BSD-licensed alternative to programs such as GNU screen.
+
+This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
+run on Solaris and AIX (although they haven't been tested in a while).
+
+Since the 1.2 release tmux depends on libevent. Download it from:
+
+ http://www.monkey.org/~provos/libevent/
+
+To build tmux from a release tarball, do:
+
+ $ ./configure && make
+ $ sudo make install
+
+To get and build the latest from version control:
+
+ $ git clone git://git.code.sf.net/p/tmux/tmux-code tmux
+ $ cd tmux
+ $ sh autogen.sh
+ $ ./configure && make
+
+For more information see https://sourceforge.net/scm/?type=git&group_id=200378
+and http://git-scm.com. Patches should be sent by email to the mailing list at
+tmux-users@lists.sourceforge.net.
+
+For documentation on using tmux, see the tmux.1 manpage. It can be viewed from
+the source tree with:
+
+ $ nroff -mdoc tmux.1|less
+
+Some common questions are answered in the FAQ file and a more extensive (but
+slightly out of date) guide is available in the OpenBSD FAQ at
+http://www.openbsd.org/faq/faq7.html#tmux. A rough todo list is in the TODO
+file and some example configurations and a Vim syntax file are in the examples
+directory.
+
+For debugging, running tmux with -v or -vv will generate server and client log
+files in the current directory.
+
+tmux mailing lists are available. Visit:
+
+ https://sourceforge.net/mail/?group_id=200378
+
+Bug reports, feature suggestions and especially code contributions are most
+welcome. Please send by email to:
+
+ tmux-users@lists.sourceforge.net
+
+This file and the CHANGES, FAQ and TODO files are licensed under the ISC
+license. Files under examples/ remain copyright their authors unless otherwise
+stated in the file but permission has been received to distribute them with
+tmux. All other files have a license and copyright notice at their start.
+
+-- Nicholas Marriott <nicm@users.sf.net>
+
+$Id$
diff --git a/SYNCING b/SYNCING
new file mode 100644
index 00000000..eba24177
--- /dev/null
+++ b/SYNCING
@@ -0,0 +1,174 @@
+Preamble
+========
+
+Tmux on SourceForge has two git repositories [1] "tmux-code" and "tmux-openbsd".
+Here's a description of them:
+
+* "tmux-code" is the portable version, the one which contains code for other
+ operating systems, and autotools, etc., which isn't found or needed in the
+ OpenBSD base system.
+
+* "tmux-openbsd" is the version of tmux in OpenBSD base system which provides
+ the basis of the portable tmux version.
+
+Note: The "tmux-openbsd" repository is actually handled by "git cvsimport"
+running at 15 minute intervals, so a commit made to OpenBSD's tmux CVS
+repository will take at least that long to appear in this git repository.
+(It might take longer, depending on the CVS mirror used to import the
+OpenBSD code).
+
+It is assumed that the person doing the sync has read/write access to the
+tmux-code repository on SourceForge already.
+
+If you've never used git before, git tracks meta-data about the committer
+and the author, as part of a commit, hence:
+
+% git config [--global] user.name "Your name"
+% git config [--global] user.email "you@yourdomain.com"
+
+Note that, if you already have this in the global ~/.gitconfig option, then
+this will be used. Setting this per-repository would involve not using the
+"--global" flag above. If you wish to use the same credentials always,
+pass the "--global" option, as shown.
+
+This is a one-off operation once the repository has been cloned, assuming
+this information has ever been set before.
+
+Cloning repositories
+====================
+
+This involves having both tmux-code and tmux-openbsd cloned, as in:
+
+% cd /some/where/useful
+% git clone ssh://${USER}@git.code.sf.net/p/tmux/tmux
+% git clone ssh://${USER}@git.code.sf.net/p/tmux/tmux-openbsd
+
+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
+these checkouts existing, skip that.
+
+Adding in git-remotes
+=====================
+
+Because the portable "tmux-code" git repository and the "tmux-openbsd"
+repository do not inherently share any history between each other, the
+history has been faked between them. This "faking of history" is something
+which has to be told to git for the purposes of comparing the "tmux" and
+"tmux-openbsd" repositories for syncing. To do this, we must reference the
+clone of the "tmux-openbsd" repository from the "tmux-code" repository, as
+shown by the following command:
+
+% cd /path/to/tmux-code
+% git remote add obsd-tmux file:///path/to/tmux-openbsd
+
+So that now, the remote "obsd-tmux" can be used to reference branches and
+commits from the "tmux-openbsd" repository, but from the context of the
+portable "tmux-code" repository, which makes sense because it's the "tmux"
+repository which will have the updates applied to them.
+
+Fetching updates
+================
+
+To ensure the latest commits from "tmux-openbsd" can be found from within
+"tmux-code", we have to ensure the "master" branch from "tmux-openbsd" is
+up-to-date first, and then reference that update in "tmux-code", as in:
+
+% cd /path/to/tmux-openbsd
+% git checkout master
+% git pull
+
+Then back in "tmux-code":
+
+% cd /path/to/tmux-code
+% git fetch obsd-tmux-code
+
+Creating the necessary branches
+===============================
+
+Now that "tmux-code" can see commits and branches from "tmux-openbsd" by way
+of the remote name "obsd-tmux", we can now create the master branch from
+"tmux-openbsd" in the "tmux-code" repository:
+
+% git checkout -b obsd-master obsd-tmux/master
+
+Adding in the fake history points
+=================================
+
+To tie both the "master" branch from "tmux-code" and the "obsd-master"
+branch from "tmux-openbsd" together, the fake history points added to the
+"tmux-code" repository need to be added. To do this, we must add an
+additional refspec line, as in:
+
+% cd /path/to/tmux-code
+% git config --add remote.origin.fetch '+refs/replace/*:refs/replace/*'
+% git fetch origin
+
+Performing the Sync
+===================
+
+Make sure the "master" branch is checked out:
+
+% git checkout master
+
+The following will show commits on OpenBSD not yet synched with "tmux-code":
+
+% git log master..obsd-master
+
+From there, merge the result in, fixing up any conflicts which might arise.
+
+% git merge obsd-master
+
+Then ensure things look correct by BULDING the result of that sync:
+
+% make clean && ./autogen.sh && ./configure && make
+
+Compare the git merge result with what's on origin/master -- that is, check
+which commits you're about to push:
+
+% git log origin/master..master
+
+And if happy:
+
+% git push origin master
+
+Release tmux for next version
+=============================
+
+1. Comment the "found_debug=yes" line in configure.ac, since releases
+ don't have debugging enabled, otherwise make(1) aborts when
+ preparing the distribution.
+
+2. Update and commit README and CHANGES. The former should be checked for
+ anything outdated and updated with a list of things that might break
+ upgrades and the latter should mention all the major changes since
+ the last version.
+
+3. Tag with:
+
+ % git tag -a 1.X
+
+ Where "1.X" is the next version.
+
+ Push the tag out with:
+
+ % git push 1.X
+
+4. Build the tarball with make dist. Now that it's using autoconf there
+ shouldn't be any weird files (such as the original and rejection files
+ from patch(1)) but it doesn't hurt taking a quick look at it.
+
+5. Split the release changes into a new file. This should be named
+ tmux-$VERSION-readme to make sourceforge show it automagically in specific
+ parts of the project page.
+
+6. Upload the tarball and the above file. Make the tarball the default
+ download by selecting all operating systems under the file details.
+
+7. Run make update-index.html upload-index.html to replace %%VERSION%%.
+
+8. Bump version in configure.ac and uncomment "found_debug=yes" to create
+ a debug build by default.
+
+9. Update freshmeat.
+
+[1] https://sourceforge.net/p/tmux/_list/git
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..a57dc932
--- /dev/null
+++ b/TODO
@@ -0,0 +1,155 @@
+NOTES
+=====
+
+This file describes rough notes regarding ideas for potential future tmux
+development. It's not necessarily guaranteed that items in this TODO file
+will ever get implemented.
+
+It is asked therefore, that anyone thinking of undertaking a task in this
+TODO file, email tmux-users@lists.sf.net to discuss the feature.
+
+Thie file is split up between tmux user interface (UI) issues, and terminal
+compatibility issues.
+
+TMUX UI ISSUES
+==============
+
+- implicitly add exec to the commands for new windows (switch to disable it)?
+- bring back detach-session to detach all clients on a session?
+- allow fnmatch for -c, so that you can, eg, detach all clients
+- garbage collect window history (100 lines at a time?) if it hasn't been used
+ in $x time
+- flags to centre screen in window
+- activity/bell should be per-window not per-link? what if it is cur win in
+ session not being watched?
+- should be able to move to a hidden pane and it would be moved into view. pane
+ number in status line/top-right would be cool for this
+- support other mouse modes (highlight etc) and use it in copy mode
+- set-remain-on-exit is a bit of a hack, some way to do it generically?
+- would be nice to be able to use "--" to mark start of command w/ neww etc
+ to avoid quoting
+- make command sequences more usable: don't require space after ;, handle
+ errors better
+- choice and more mode would be better per client than per window?
+- hooks to which commands may be attached, for example: tmux add-hook
+ "new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
+ $HOME/.tmux-session.conf
+- way to set socket path from config file
+- warts on current naming:
+ - display-time but message-fg/bg/attr
+ - list-* vs show-*
+ - server-info
+ - up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
+ - split-window -> split-pane??
+- some way to force a screen to use the entire terminal even if it is forced
+ to be smaller by other clients. pan smaller terminal? (like screen F)
+ -- idea of a "view" onto a window, need base x/y offsets for redraw
+- commands should be able to succeed or fail and have || or && for command
+ lists
+- some way to keep a command running continually and just use its last line of
+ output
+- UTF-8 to a non-UTF-8 terminal should not be able to balls up
+ the terminal - www/ruby-addressable; make regress
+- support esc-esc to quit in modes
+- fix ctrl+F1-F4 output. to what?
+- better utf8 support: window names, prompt input, message display
+- option to move copy mode indicator into status line
+- selection behaviour closer to vi in vi mode
+- live update: server started with -U connects to server, requests sessions and
+ windows, receives fds
+- sort out inheriting config from shell on new sessions/windows:
+ should pick up default-path/termios/etc from client if possible,
+ else leave empty/default
+- link panes into multiple windows
+- bells should be passed between sessions with visual-bell etc
+ sequence until its shell exits, to allow them to be used from the config file
+- better session sharing: create-socket command to create socket somewhere (-r
+ flag for readonly)
+- multiline status line (no?)
+- support title stack, both internally and externally
+ http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
+- some way to pad # stuff with spaces, #!2T maybe
+- a binding to "scroll down and exit at bottom" copy mode
+- some way to pass keystrokes in copy mode through to underlying window. why?
+- last window update time and # replacement for it for display-message
+- find-window across sessions - other ways to make session handling easier?
+- ' and " should be parsed the same (eg "\e" vs '\e') in config and command
+ prompt?
+- command to toggle selection not to move it in copy-mode
+- audit of escape sequence support vs xterm
+- support binding keys to mouse (mouse-select-pane -> mouse-keys or something,
+ mouse click == select-pane -t %%, mouse scroll up == copy-mode)
+- bind commands to key sequences? -- make it so ALL keys go through a table,
+ first an implicit table in which C-b is the only default binding to a
+ command that says "next key from $othertable" and so on. means -n can
+ go away as well
+- monitor, bell etc should monitor /all/ panes in the window not just one
+- a history of commands that can be reversed (reverse member of each command,
+ and a buffer)
+- info() when changing to same window
+- way to add dest for break-pane; maybe some easier way to unbreak-pane
+- case insensitive searching
+- incremental searching in copy mode.
+- configurable borders and empty space filler for when panes < window?
+- mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets the
+ flag on w/o checking the others before calling tty_update_mode)
+- pass shell commands as argv rather than strings, allow them to be specified
+ in commands without quotes
+- named buffers and allow gaps in the stack
+- monitor-activity is broken in several ways with multiple clients
+- monitor-activity should be more powerful (eg set a region)
+- maybe a way to put pane names instead of window names in status line
+- support for borderless panes
+- wait-for command 20130222153957.GY6782@yelena.nicm.ath.cx
+- last-pane across sessions
+- panes should have names like windows
+- command-prompt doesn't work if made read-only. why?
+- option to quote format eg #{session_name:quoted}
+- formats need conditions for >0 (for #P)
+- fetch full command line on !Linux, and add option to strip prefixes
+ such as "sh " "/bin/sh " etc etc
+- synchronize-windows option
+- append to buffer in copy mode
+- way to paste w/o trailing whitespace
+- flag to switch-client to switch all clients
+- history of layouts and undo/redo flags to selectl
+- way to tag a layout as a number/name
+- optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
+- support multibyte key strings
+- allow commands to be executed when certain patterns in a screen
+ are clicked on with the mouse
+- flag to make next/previous commands skip a window
+- way to do tmux command/run-shell from mode keys
+- send command to all windows
+- choose-pane command (augment choose-tree to do this?)
+- choose-mode and copy-mode are very similar. Perhaps make choose-mode a subset
+ of copy-mode in that it inherits key-bindings and other traits but not all
+- add -c for new-session like new-window
+- flag to choose-* for sort order (eg sort windows/sessions/clients by last
+ used time) - perhaps using formats (but what about numeric sort)?
+- instead of separate window and session options, just one master options list
+ with each option having a type (window or session), then options on window,
+ on session, and global. for window options we look window->session->global,
+ and for session we look session->global
+- maybe keep last layout + size around and if size reverts just put it back
+- way to set hints/limits about pane size for resizing
+- revamp layouts: they are too complicated, should be more closely integrated,
+ should support hints, layout sets should just be a special case of custom
+ layouts, and we should support panes that are not attached to a cell at
+ all. this could be the time to introduce panelink to replace layout_cell
+- run-shell/if-shell should support formats
+- attach should take a pane and select it as well as attaching
+- attach should have a flag to create session if it doesn't exist. or better
+ new a flag to attach it
+
+TERMINAL ISSUES
+================
+
+- use a better termcap internally instead of screen, perhaps xterm
+- clear window title on exit (see using xterm title stack)
+- get it passing all the vttest tests that don't require resizing the terminal
+- support for bce
+- use screen-256color when started on 256 colour terminal?
+* We need a tmux terminfo entry to document the extensions we are using in
+ upstream terminfo. Must NOT change (only add or remove) anything from
+ TERM=screen so we can fallback!
diff --git a/arguments.c b/arguments.c
index c15832a4..4d54ff85 100644
--- a/arguments.c
+++ b/arguments.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,7 +18,6 @@
#include <sys/types.h>
-#include <bitstring.h>
#include <stdlib.h>
#include <string.h>
diff --git a/array.h b/array.h
index c811bf6d..11e963bc 100644
--- a/array.h
+++ b/array.h
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/attributes.c b/attributes.c
index 84e4f9c6..f9871108 100644
--- a/attributes.c
+++ b/attributes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 00000000..300b54db
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+# $Id$
+
+if [ "x$(uname)" = "xOpenBSD" ]; then
+ [ -z "$AUTOMAKE_VERSION" ] && export AUTOMAKE_VERSION=1.10
+ [ -z "$AUTOCONF_VERSION" ] && export AUTOCONF_VERSION=2.65
+fi
+
+die()
+{
+ echo "$@" >&2
+ exit 1
+}
+
+mkdir -p etc
+aclocal || die "aclocal failed"
+automake --add-missing --force-missing --copy --foreign || die "automake failed"
+autoreconf || die "autoreconf failed"
diff --git a/cfg.c b/cfg.c
index c625a2fb..1153de67 100644
--- a/cfg.c
+++ b/cfg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/client.c b/client.c
index 70e7f1ec..91f47650 100644
--- a/client.c
+++ b/client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -225,7 +225,9 @@ client_main(int argc, char **argv, int flags)
}
/* Set process title, log and signals now this is the client. */
+#ifdef HAVE_SETPROCTITLE
setproctitle("client (%s)", socket_path);
+#endif
logfile("client");
/* Create imsg. */
@@ -245,7 +247,9 @@ client_main(int argc, char **argv, int flags)
cfmakeraw(&tio);
tio.c_iflag = ICRNL|IXANY;
tio.c_oflag = OPOST|ONLCR;
+#ifdef NOKERNINFO
tio.c_lflag = NOKERNINFO;
+#endif
tio.c_cflag = CREAD|CS8|HUPCL;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
diff --git a/clock.c b/clock.c
index 00d818be..49a883cf 100644
--- a/clock.c
+++ b/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index f5f2778d..07185737 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index d9b65bec..71e79ea0 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index bac332a2..8ed9a1a6 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-capture-pane.c b/cmd-capture-pane.c
index 779cbe08..f59dc2d6 100644
--- a/cmd-capture-pane.c
+++ b/cmd-capture-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c
index 8713815d..e6b79d91 100644
--- a/cmd-choose-buffer.c
+++ b/cmd-choose-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-choose-client.c b/cmd-choose-client.c
index df57f9cf..40752a70 100644
--- a/cmd-choose-client.c
+++ b/cmd-choose-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index f22f17c2..e2d382b3 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
diff --git a/cmd-clear-history.c b/cmd-clear-history.c
index 768ba86d..aebaa27d 100644
--- a/cmd-clear-history.c
+++ b/cmd-clear-history.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-clock-mode.c b/cmd-clock-mode.c
index b1837004..872f3d53 100644
--- a/cmd-clock-mode.c
+++ b/cmd-clock-mode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 3b773316..3bb79ed9 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 6282be2e..e670f69c 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index 59b5a9e5..f014be83 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-delete-buffer.c b/cmd-delete-buffer.c
index 6e425b57..bc3982ca 100644
--- a/cmd-delete-buffer.c
+++ b/cmd-delete-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-detach-client.c b/cmd-detach-client.c
index 17b437ab..6e00e079 100644
--- a/cmd-detach-client.c
+++ b/cmd-detach-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-display-message.c b/cmd-display-message.c
index 52d47a4c..485ccf08 100644
--- a/cmd-display-message.c
+++ b/cmd-display-message.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index a97a1809..4a8731a4 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-find-window.c b/cmd-find-window.c
index f757d10f..02f19307 100644
--- a/cmd-find-window.c
+++ b/cmd-find-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-has-session.c b/cmd-has-session.c
index 28e3aea3..c4286b86 100644
--- a/cmd-has-session.c
+++ b/cmd-has-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index e810b0fc..d1cbd7f3 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
diff --git a/cmd-join-pane.c b/cmd-join-pane.c
index cf17e7d9..2cf587e0 100644
--- a/cmd-join-pane.c
+++ b/cmd-join-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
@@ -19,7 +19,6 @@
#include <sys/types.h>
-#include <paths.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c
index ba3bfd20..40761350 100644
--- a/cmd-kill-pane.c
+++ b/cmd-kill-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-kill-server.c b/cmd-kill-server.c
index 808dca59..a6065460 100644
--- a/cmd-kill-server.c
+++ b/cmd-kill-server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-kill-session.c b/cmd-kill-session.c
index 095fb9bb..a12cc8a4 100644
--- a/cmd-kill-session.c
+++ b/cmd-kill-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-kill-window.c b/cmd-kill-window.c
index dcb1fd28..34b97499 100644
--- a/cmd-kill-window.c
+++ b/cmd-kill-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-link-window.c b/cmd-link-window.c
index c7dfa5aa..2be8ace0 100644
--- a/cmd-link-window.c
+++ b/cmd-link-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-buffers.c b/cmd-list-buffers.c
index 54284d55..58af0020 100644
--- a/cmd-list-buffers.c
+++ b/cmd-list-buffers.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index e0f8558e..59f63099 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-commands.c b/cmd-list-commands.c
index 7073d5f8..1bf6e703 100644
--- a/cmd-list-commands.c
+++ b/cmd-list-commands.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index 1f568909..78998b66 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-panes.c b/cmd-list-panes.c
index 910c19bc..0d498e28 100644
--- a/cmd-list-panes.c
+++ b/cmd-list-panes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c
index 14ac4808..61c12f4e 100644
--- a/cmd-list-sessions.c
+++ b/cmd-list-sessions.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list-windows.c b/cmd-list-windows.c
index c709e471..5c2a2b95 100644
--- a/cmd-list-windows.c
+++ b/cmd-list-windows.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-list.c b/cmd-list.c
index 82ae7480..08e2067c 100644
--- a/cmd-list.c
+++ b/cmd-list.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c
index 698210d8..3be14d6a 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
diff --git a/cmd-lock-server.c b/cmd-lock-server.c
index 8491c8b1..0b6aafe8 100644
--- a/cmd-lock-server.c
+++ b/cmd-lock-server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-move-window.c b/cmd-move-window.c
index 945e9daa..1a147c7e 100644
--- a/cmd-move-window.c
+++ b/cmd-move-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 653db876..4eebe632 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-new-window.c b/cmd-new-window.c
index eac0df44..cfc0b8bd 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c
index 1cfc17c8..b07c9faf 100644
--- a/cmd-paste-buffer.c
+++ b/cmd-paste-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
-#include <vis.h>
#include "tmux.h"
diff --git a/cmd-pipe-pane.c b/cmd-pipe-pane.c
index 5de675df..aa72c699 100644
--- a/cmd-pipe-pane.c
+++ b/cmd-pipe-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,7 +21,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <paths.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
diff --git a/cmd-queue.c b/cmd-queue.c
index b1c0a4eb..c5f75f40 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index eff692dd..7d9d539f 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-rename-session.c b/cmd-rename-session.c
index c94b460b..3f8a9d8f 100644
--- a/cmd-rename-session.c
+++ b/cmd-rename-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-rename-window.c b/cmd-rename-window.c
index 34b03f98..c756ba1f 100644
--- a/cmd-rename-window.c
+++ b/cmd-rename-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index 41c15269..ca2a6cd3 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index 0aae0331..4486c91f 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index a446794b..35bd3471 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c
index 7af592b3..75ca7292 100644
--- a/cmd-rotate-window.c
+++ b/cmd-rotate-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index ef1dbdd4..7c7d333c 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
diff --git a/cmd-save-buffer.c b/cmd-save-buffer.c
index 29f71837..52914a94 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -22,7 +22,6 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include <vis.h>
#include "tmux.h"
diff --git a/cmd-select-layout.c b/cmd-select-layout.c
index aa73e500..ae1be4c4 100644
--- a/cmd-select-layout.c
+++ b/cmd-select-layout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index 77be368f..b8a12671 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-select-window.c b/cmd-select-window.c
index 6206ae4b..c15d5858 100644
--- a/cmd-select-window.c
+++ b/cmd-select-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 3ee3dbe6..37d4fd2b 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c
deleted file mode 100644
index 04556507..00000000
--- a/cmd-send-prefix.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* $OpenBSD$ */
-
-/*
- * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include "tmux.h"
-
-/*
- * Send prefix key as a key.
- */
-
-enum cmd_retval cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
-
-const struct cmd_entry cmd_send_prefix_entry = {
- "send-prefix", NULL,
- "2t:", 0, 0,
- "[-2] " CMD_TARGET_PANE_USAGE,
- 0,
- NULL,
- NULL,
- cmd_send_prefix_exec
-};
-
-enum cmd_retval
-cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
-{
- struct args *args = self->args;
- struct session *s;
- struct window_pane *wp;
- int key;
-
- if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
- return (CMD_RETURN_ERROR);
-
- if (args_has(args, '2'))
- key = options_get_number(&s->options, "prefix2");
- else
- key = options_get_number(&s->options, "prefix");
- window_pane_key(wp, s, key);
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-server-info.c b/cmd-server-info.c
index 07b224a1..8eba172a 100644
--- a/cmd-server-info.c
+++ b/cmd-server-info.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,7 +23,6 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include <vis.h>
#include "tmux.h"
@@ -66,7 +65,8 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq)
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
- cmdq_print(cmdq, "pid %ld, started %s", (long) getpid(), tim);
+ cmdq_print(cmdq,
+ "tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
cmdq_print(cmdq, "socket path %s, debug level %d", socket_path,
debug_level);
if (uname(&un) >= 0) {
diff --git a/cmd-set-buffer.c b/cmd-set-buffer.c
index 46450e21..46d28ff2 100644
--- a/cmd-set-buffer.c
+++ b/cmd-set-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-set-environment.c b/cmd-set-environment.c
index 6e75a294..0f0365aa 100644
--- a/cmd-set-environment.c
+++ b/cmd-set-environment.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 6c0fefbf..a46460a8 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-show-buffer.c b/cmd-show-buffer.c
deleted file mode 100644
index 0af82972..00000000
--- a/cmd-show-buffer.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* $OpenBSD$ */
-
-/*
- * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-
-#include <stdlib.h>
-#include <vis.h>
-
-#include "tmux.h"
-
-/*
- * Show a paste buffer.
- */
-
-enum cmd_retval cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
-
-const struct cmd_entry cmd_show_buffer_entry = {
- "show-buffer", "showb",
- "b:", 0, 0,
- CMD_BUFFER_USAGE,
- 0,
- NULL,
- NULL,
- cmd_show_buffer_exec
-};
-
-enum cmd_retval
-cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
-{
- struct args *args = self->args;
- struct session *s;
- struct paste_buffer *pb;
- int buffer;
- char *in, *buf, *ptr, *cause;
- size_t size, len;
- u_int width;
-
- if ((s = cmd_find_session(ctx, NULL, 0)) == NULL)
- return (CMD_RETURN_ERROR);
-
- if (!args_has(args, 'b')) {
- if ((pb = paste_get_top(&global_buffers)) == NULL) {
- ctx->error(ctx, "no buffers");
- return (CMD_RETURN_ERROR);
- }
- } else {
- buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
- if (cause != NULL) {
- ctx->error(ctx, "buffer %s", cause);
- free(cause);
- return (CMD_RETURN_ERROR);
- }
-
- pb = paste_get_index(&global_buffers, buffer);
- if (pb == NULL) {
- ctx->error(ctx, "no buffer %d", buffer);
- return (CMD_RETURN_ERROR);
- }
- }
-
- size = pb->size;
- if (size > SIZE_MAX / 4 - 1)
- size = SIZE_MAX / 4 - 1;
- in = xmalloc(size * 4 + 1);
- strvisx(in, pb->data, size, VIS_OCTAL|VIS_TAB);
-
- width = s->sx;
- if (ctx->cmdclient != NULL)
- width = ctx->cmdclient->tty.sx;
-
- buf = xmalloc(width + 1);
- len = 0;
-
- ptr = in;
- do {
- buf[len++] = *ptr++;
-
- if (len == width || buf[len - 1] == '\n') {
- if (buf[len - 1] == '\n')
- len--;
- buf[len] = '\0';
-
- ctx->print(ctx, "%s", buf);
- len = 0;
- }
- } while (*ptr != '\0');
-
- if (len != 0) {
- buf[len] = '\0';
- ctx->print(ctx, "%s", buf);
- }
- free(buf);
-
- free(in);
-
- return (CMD_RETURN_NORMAL);
-}
diff --git a/cmd-show-environment.c b/cmd-show-environment.c
index cb53e84c..ffe98bcc 100644
--- a/cmd-show-environment.c
+++ b/cmd-show-environment.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index cbf083a7..bc2424ad 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-show-options.c b/cmd-show-options.c
index 57e49a33..e2f78e12 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-source-file.c b/cmd-source-file.c
index 1bd2bb0a..827d4c00 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 98bbd423..601dcb17 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,7 +18,6 @@
#include <sys/types.h>
-#include <paths.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/cmd-start-server.c b/cmd-start-server.c
index c926b5fe..cba2403b 100644
--- a/cmd-start-server.c
+++ b/cmd-start-server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-string.c b/cmd-string.c
index f785b842..7e84eda6 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-suspend-client.c b/cmd-suspend-client.c
index dda0f977..101658b1 100644
--- a/cmd-suspend-client.c
+++ b/cmd-suspend-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index e7ea6242..d484f4e2 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-swap-window.c b/cmd-swap-window.c
index ed175480..f9a2cb1b 100644
--- a/cmd-swap-window.c
+++ b/cmd-swap-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index ea5012ed..9adb2146 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index 88c81270..dc037dde 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c
index 78c4b390..39cdd8ed 100644
--- a/cmd-unlink-window.c
+++ b/cmd-unlink-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd-wait-for.c b/cmd-wait-for.c
index 3a8d8ea4..d40ba49e 100644
--- a/cmd-wait-for.c
+++ b/cmd-wait-for.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/cmd.c b/cmd.c
index d0348704..eecac462 100644
--- a/cmd.c
+++ b/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,7 +20,6 @@
#include <sys/time.h>
#include <fnmatch.h>
-#include <paths.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
@@ -1334,7 +1333,7 @@ cmd_get_default_path(struct cmd_q *cmdq, const char *cwd)
if (c != NULL && c->session == NULL && c->cwd != NULL)
root = c->cwd;
else if (s->curw != NULL)
- root = get_proc_cwd(s->curw->window->active->fd);
+ root = osdep_get_cwd(s->curw->window->active->fd);
else
return (s->cwd);
skip = 0;
diff --git a/colour.c b/colour.c
index ff492687..eef31a30 100644
--- a/colour.c
+++ b/colour.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/compat.h b/compat.h
new file mode 100644
index 00000000..b9ee7ba1
--- /dev/null
+++ b/compat.h
@@ -0,0 +1,245 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef COMPAT_H
+#define COMPAT_H
+
+#ifndef __GNUC__
+#define __attribute__(a)
+#endif
+
+#ifndef __dead
+#define __dead __attribute__ ((__noreturn__))
+#endif
+#ifndef __packed
+#define __packed __attribute__ ((__packed__))
+#endif
+
+#ifndef HAVE_BSD_TYPES
+typedef uint8_t u_int8_t;
+typedef uint16_t u_int16_t;
+typedef uint32_t u_int32_t;
+typedef uint64_t u_int64_t;
+#endif
+
+#ifndef HAVE_PATHS_H
+#define _PATH_BSHELL "/bin/sh"
+#define _PATH_TMP "/tmp/"
+#define _PATH_DEVNULL "/dev/null"
+#define _PATH_TTY "/dev/tty"
+#define _PATH_DEV "/dev/"
+#endif
+
+#ifdef HAVE_QUEUE_H
+#include <sys/queue.h>
+#else
+#include "compat/queue.h"
+#endif
+
+#ifdef HAVE_TREE_H
+#include <sys/tree.h>
+#else
+#include "compat/tree.h"
+#endif
+
+#ifdef HAVE_BITSTRING_H
+#include <bitstring.h>
+#else
+#include "compat/bitstring.h"
+#endif
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifdef HAVE_FORKPTY
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#endif
+
+#ifdef HAVE_VIS
+#include <vis.h>
+#else
+#include "compat/vis.h"
+#endif
+
+#ifdef HAVE_IMSG
+#include <imsg.h>
+#else
+#include "compat/imsg.h"
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#else
+#include <inttypes.h>
+#endif
+
+#ifdef BROKEN_CMSG_FIRSTHDR
+#undef CMSG_FIRSTHDR
+#define CMSG_FIRSTHDR(mhdr) \
+ ((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
+ (struct cmsghdr *)(mhdr)->msg_control : \
+ (struct cmsghdr *)NULL)
+#endif
+
+#ifndef CMSG_ALIGN
+#ifdef _CMSG_DATA_ALIGN
+#define CMSG_ALIGN _CMSG_DATA_ALIGN
+#else
+#define CMSG_ALIGN(len) (((len) + sizeof(long) - 1) & ~(sizeof(long) - 1))
+#endif
+#endif
+
+#ifndef CMSG_SPACE
+#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
+#endif
+
+#ifndef CMSG_LEN
+#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
+#endif
+
+#ifndef INFTIM
+#define INFTIM -1
+#endif
+
+#ifndef WAIT_ANY
+#define WAIT_ANY -1
+#endif
+
+#ifndef SUN_LEN
+#define SUN_LEN(sun) (sizeof (sun)->sun_path)
+#endif
+
+#ifndef timercmp
+#define timercmp(tvp, uvp, cmp) \
+ (((tvp)->tv_sec == (uvp)->tv_sec) ? \
+ ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec))
+#endif
+
+#ifndef timeradd
+#define timeradd(tvp, uvp, vvp) \
+ do { \
+ (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
+ if ((vvp)->tv_usec >= 1000000) { \
+ (vvp)->tv_sec++; \
+ (vvp)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+#endif
+
+#ifndef TTY_NAME_MAX
+#define TTY_NAME_MAX 32
+#endif
+
+#ifndef HAVE_BZERO
+#undef bzero
+#define bzero(buf, len) memset(buf, 0, len);
+#endif
+
+#ifndef HAVE_CLOSEFROM
+/* closefrom.c */
+void closefrom(int);
+#endif
+
+#ifndef HAVE_STRCASESTR
+/* strcasestr.c */
+char *strcasestr(const char *, const char *);
+#endif
+
+#ifndef HAVE_STRSEP
+/* strsep.c */
+char *strsep(char **, const char *);
+#endif
+
+#ifndef HAVE_STRTONUM
+/* strtonum.c */
+long long strtonum(const char *, long long, long long, const char **);
+#endif
+
+#ifndef HAVE_STRLCPY
+/* strlcpy.c */
+size_t strlcpy(char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_STRLCAT
+/* strlcat.c */
+size_t strlcat(char *, const char *, size_t);
+#endif
+
+#ifndef HAVE_DAEMON
+/* daemon.c */
+int daemon(int, int);
+#endif
+
+#ifndef HAVE_B64_NTOP
+/* b64_ntop.c */
+int b64_ntop(const char *, size_t, char *, size_t);
+#endif
+
+#ifndef HAVE_FORKPTY
+/* forkpty.c */
+#include <sys/ioctl.h>
+pid_t forkpty(int *, char *, struct termios *, struct winsize *);
+#endif
+
+#ifndef HAVE_ASPRINTF
+/* asprintf.c */
+int asprintf(char **, const char *, ...);
+int vasprintf(char **, const char *, va_list);
+#endif
+
+#ifndef HAVE_FGETLN
+/* fgetln.c */
+char *fgetln(FILE *, size_t *);
+#endif
+
+#ifndef HAVE_SETENV
+/* setenv.c */
+int setenv(const char *, const char *, int);
+int unsetenv(const char *);
+#endif
+
+#ifdef HAVE_GETOPT
+#include <getopt.h>
+#else
+/* getopt.c */
+extern int BSDopterr;
+extern int BSDoptind;
+extern int BSDoptopt;
+extern int BSDoptreset;
+extern char *BSDoptarg;
+int BSDgetopt(int, char *const *, const char *);
+#define getopt(ac, av, o) BSDgetopt(ac, av, o)
+#define opterr BSDopterr
+#define optind BSDoptind
+#define optopt BSDoptopt
+#define optreset BSDoptreset
+#define optarg BSDoptarg
+#endif
+
+#endif /* COMPAT_H */
diff --git a/compat/asprintf.c b/compat/asprintf.c
new file mode 100644
index 00000000..66f00996
--- /dev/null
+++ b/compat/asprintf.c
@@ -0,0 +1,65 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#else
+#include <inttypes.h>
+#endif
+#include <string.h>
+
+#include "tmux.h"
+
+int
+asprintf(char **ret, const char *fmt, ...)
+{
+ va_list ap;
+ int n;
+
+ va_start(ap, fmt);
+ n = vasprintf(ret, fmt, ap);
+ va_end(ap);
+
+ return (n);
+}
+
+int
+vasprintf(char **ret, const char *fmt, va_list ap)
+{
+ int n;
+ va_list ap2;
+
+ va_copy(ap2, ap);
+
+ if ((n = vsnprintf(NULL, 0, fmt, ap)) < 0)
+ goto error;
+
+ *ret = xmalloc(n + 1);
+ if ((n = vsnprintf(*ret, n + 1, fmt, ap2)) < 0) {
+ free(*ret);
+ goto error;
+ }
+
+ return (n);
+
+error:
+ *ret = NULL;
+ return (-1);
+}
diff --git a/compat/b64_ntop.c b/compat/b64_ntop.c
new file mode 100644
index 00000000..2b4dc2d4
--- /dev/null
+++ b/compat/b64_ntop.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ uint8_t input[3];
+ uint8_t output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
diff --git a/compat/bitstring.h b/compat/bitstring.h
new file mode 100644
index 00000000..28817c08
--- /dev/null
+++ b/compat/bitstring.h
@@ -0,0 +1,129 @@
+/* $Id$ */
+/* $OpenBSD: bitstring.h,v 1.5 2003/06/02 19:34:12 millert Exp $ */
+/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Vixie.
+ *
+ * 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.
+ *
+ * @(#)bitstring.h 8.1 (Berkeley) 7/19/93
+ */
+
+#ifndef _BITSTRING_H_
+#define _BITSTRING_H_
+
+/* modified for SV/AT and bitstring bugfix by M.R.Murphy, 11oct91
+ * bitstr_size changed gratuitously, but shorter
+ * bit_alloc spelling error fixed
+ * the following were efficient, but didn't work, they've been made to
+ * work, but are no longer as efficient :-)
+ * bit_nclear, bit_nset, bit_ffc, bit_ffs
+ */
+typedef unsigned char bitstr_t;
+
+/* internal macros */
+ /* byte of the bitstring bit is in */
+#define _bit_byte(bit) \
+ ((bit) >> 3)
+
+ /* mask for the bit within its byte */
+#define _bit_mask(bit) \
+ (1 << ((bit)&0x7))
+
+/* external macros */
+ /* bytes in a bitstring of nbits bits */
+#define bitstr_size(nbits) \
+ (((nbits) + 7) >> 3)
+
+ /* allocate a bitstring */
+#define bit_alloc(nbits) \
+ (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t))
+
+ /* allocate a bitstring on the stack */
+#define bit_decl(name, nbits) \
+ ((name)[bitstr_size(nbits)])
+
+ /* is bit N of bitstring name set? */
+#define bit_test(name, bit) \
+ ((name)[_bit_byte(bit)] & _bit_mask(bit))
+
+ /* set bit N of bitstring name */
+#define bit_set(name, bit) \
+ ((name)[_bit_byte(bit)] |= _bit_mask(bit))
+
+ /* clear bit N of bitstring name */
+#define bit_clear(name, bit) \
+ ((name)[_bit_byte(bit)] &= ~_bit_mask(bit))
+
+ /* clear bits start ... stop in bitstring */
+#define bit_nclear(name, start, stop) do { \
+ register bitstr_t *_name = name; \
+ register int _start = start, _stop = stop; \
+ while (_start <= _stop) { \
+ bit_clear(_name, _start); \
+ _start++; \
+ } \
+} while(0)
+
+ /* set bits start ... stop in bitstring */
+#define bit_nset(name, start, stop) do { \
+ register bitstr_t *_name = name; \
+ register int _start = start, _stop = stop; \
+ while (_start <= _stop) { \
+ bit_set(_name, _start); \
+ _start++; \
+ } \
+} while(0)
+
+ /* find first bit clear in name */
+#define bit_ffc(name, nbits, value) do { \
+ register bitstr_t *_name = name; \
+ register int _bit, _nbits = nbits, _value = -1; \
+ for (_bit = 0; _bit < _nbits; ++_bit) \
+ if (!bit_test(_name, _bit)) { \
+ _value = _bit; \
+ break; \
+ } \
+ *(value) = _value; \
+} while(0)
+
+ /* find first bit set in name */
+#define bit_ffs(name, nbits, value) do { \
+ register bitstr_t *_name = name; \
+ register int _bit, _nbits = nbits, _value = -1; \
+ for (_bit = 0; _bit < _nbits; ++_bit) \
+ if (bit_test(_name, _bit)) { \
+ _value = _bit; \
+ break; \
+ } \
+ *(value) = _value; \
+} while(0)
+
+#endif /* !_BITSTRING_H_ */
diff --git a/compat/closefrom.c b/compat/closefrom.c
new file mode 100644
index 00000000..74714c13
--- /dev/null
+++ b/compat/closefrom.c
@@ -0,0 +1,111 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2004-2005 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.
+ */
+
+#include "tmux.h"
+
+#ifndef HAVE_CLOSEFROM
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdio.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifndef OPEN_MAX
+# define OPEN_MAX 256
+#endif
+
+#if 0
+__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
+#endif /* lint */
+
+/*
+ * Close all file descriptors greater than or equal to lowfd.
+ */
+#ifdef HAVE_FCNTL_CLOSEM
+void
+closefrom(int lowfd)
+{
+ (void) fcntl(lowfd, F_CLOSEM, 0);
+}
+#else
+void
+closefrom(int lowfd)
+{
+ long fd, maxfd;
+#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+ char fdpath[PATH_MAX], *endp;
+ struct dirent *dent;
+ DIR *dirp;
+ int len;
+
+ /* Check for a /proc/$$/fd directory. */
+ len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
+ if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
+ while ((dent = readdir(dirp)) != NULL) {
+ fd = strtol(dent->d_name, &endp, 10);
+ if (dent->d_name != endp && *endp == '\0' &&
+ fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
+ (void) close((int) fd);
+ }
+ (void) closedir(dirp);
+ } else
+#endif
+ {
+ /*
+ * Fall back on sysconf() or getdtablesize(). We avoid checking
+ * resource limits since it is possible to open a file descriptor
+ * and then drop the rlimit such that it is below the open fd.
+ */
+#ifdef HAVE_SYSCONF
+ maxfd = sysconf(_SC_OPEN_MAX);
+#else
+ maxfd = getdtablesize();
+#endif /* HAVE_SYSCONF */
+ if (maxfd < 0)
+ maxfd = OPEN_MAX;
+
+ for (fd = lowfd; fd < maxfd; fd++)
+ (void) close((int) fd);
+ }
+}
+#endif /* !HAVE_FCNTL_CLOSEM */
+#endif /* HAVE_CLOSEFROM */
diff --git a/compat/daemon.c b/compat/daemon.c
new file mode 100644
index 00000000..661f7fd5
--- /dev/null
+++ b/compat/daemon.c
@@ -0,0 +1,66 @@
+/* $Id$ */
+/* $OpenBSD: daemon.c,v 1.6 2005/08/08 08:05:33 espie Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ * 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.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "tmux.h"
+
+int
+daemon(int nochdir, int noclose)
+{
+ int fd;
+
+ switch (fork()) {
+ case -1:
+ return (-1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+
+ if (setsid() == -1)
+ return (-1);
+
+ if (!nochdir)
+ (void)chdir("/");
+
+ if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+ (void)dup2(fd, STDIN_FILENO);
+ (void)dup2(fd, STDOUT_FILENO);
+ (void)dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ (void)close (fd);
+ }
+ return (0);
+}
diff --git a/compat/fgetln.c b/compat/fgetln.c
new file mode 100644
index 00000000..08ddc840
--- /dev/null
+++ b/compat/fgetln.c
@@ -0,0 +1,86 @@
+/* $Id$ */
+/* $NetBSD: fgetln.c,v 1.3 2007/08/07 02:06:58 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "tmux.h"
+
+char *
+fgetln(FILE *fp, size_t *len)
+{
+ static char *buf = NULL;
+ static size_t bufsiz = 0;
+ char *ptr;
+
+
+ if (buf == NULL) {
+ bufsiz = BUFSIZ;
+ if ((buf = malloc(bufsiz)) == NULL)
+ return NULL;
+ }
+
+ if (fgets(buf, bufsiz, fp) == NULL)
+ return NULL;
+
+ *len = 0;
+ while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
+ size_t nbufsiz = bufsiz + BUFSIZ;
+ char *nbuf = realloc(buf, nbufsiz);
+
+ if (nbuf == NULL) {
+ int oerrno = errno;
+ free(buf);
+ errno = oerrno;
+ buf = NULL;
+ return NULL;
+ } else
+ buf = nbuf;
+
+ *len = bufsiz;
+ if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL)
+ return buf;
+
+ bufsiz = nbufsiz;
+ }
+
+ *len = (ptr - buf) + 1;
+ return buf;
+}
+
diff --git a/compat/forkpty-aix.c b/compat/forkpty-aix.c
new file mode 100644
index 00000000..db9c2e71
--- /dev/null
+++ b/compat/forkpty-aix.c
@@ -0,0 +1,95 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+pid_t
+forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
+{
+ int slave, fd;
+ char *path;
+ pid_t pid;
+
+ if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1)
+ return (-1);
+
+ if ((path = ttyname(*master)) == NULL)
+ goto out;
+ if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
+ goto out;
+
+ switch (pid = fork()) {
+ case -1:
+ goto out;
+ case 0:
+ close(*master);
+
+ fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
+ if (fd >= 0) {
+ ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
+ }
+
+ if (setsid() < 0)
+ fatal("setsid");
+
+ fd = open(_PATH_TTY, O_RDWR|O_NOCTTY);
+ if (fd >= 0)
+ fatalx("open succeeded (failed to disconnect)");
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ fatal("open failed");
+ close(fd);
+
+ fd = open("/dev/tty", O_WRONLY);
+ if (fd < 0)
+ fatal("open failed");
+ close(fd);
+
+ if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
+ fatal("tcsetattr failed");
+ if (ioctl(slave, TIOCSWINSZ, ws) == -1)
+ fatal("ioctl failed");
+
+ dup2(slave, 0);
+ dup2(slave, 1);
+ dup2(slave, 2);
+ if (slave > 2)
+ close(slave);
+ return (0);
+ }
+
+ close(slave);
+ return (pid);
+
+out:
+ if (*master != -1)
+ close(*master);
+ if (slave != -1)
+ close(slave);
+ return (-1);
+}
diff --git a/compat/forkpty-hpux.c b/compat/forkpty-hpux.c
new file mode 100644
index 00000000..90452f8d
--- /dev/null
+++ b/compat/forkpty-hpux.c
@@ -0,0 +1,89 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+pid_t
+forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
+{
+ int slave;
+ char *path;
+ pid_t pid;
+
+ if ((*master = open("/dev/ptmx", O_RDWR|O_NOCTTY)) == -1)
+ return (-1);
+ if (grantpt(*master) != 0)
+ goto out;
+ if (unlockpt(*master) != 0)
+ goto out;
+
+ if ((path = ptsname(*master)) == NULL)
+ goto out;
+ if (name != NULL)
+ strlcpy(name, path, TTY_NAME_MAX);
+ if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
+ goto out;
+
+ switch (pid = fork()) {
+ case -1:
+ goto out;
+ case 0:
+ close(*master);
+
+ setsid();
+#ifdef TIOCSCTTY
+ if (ioctl(slave, TIOCSCTTY, NULL) == -1)
+ fatal("ioctl failed");
+#endif
+
+ if (ioctl(slave, I_PUSH, "ptem") == -1)
+ fatal("ioctl failed");
+ if (ioctl(slave, I_PUSH, "ldterm") == -1)
+ fatal("ioctl failed");
+
+ if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
+ fatal("tcsetattr failed");
+ if (ioctl(slave, TIOCSWINSZ, ws) == -1)
+ fatal("ioctl failed");
+
+ dup2(slave, 0);
+ dup2(slave, 1);
+ dup2(slave, 2);
+ if (slave > 2)
+ close(slave);
+ return (0);
+ }
+
+ close(slave);
+ return (pid);
+
+out:
+ if (*master != -1)
+ close(*master);
+ if (slave != -1)
+ close(slave);
+ return (-1);
+}
diff --git a/compat/forkpty-sunos.c b/compat/forkpty-sunos.c
new file mode 100644
index 00000000..90452f8d
--- /dev/null
+++ b/compat/forkpty-sunos.c
@@ -0,0 +1,89 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+pid_t
+forkpty(int *master, char *name, struct termios *tio, struct winsize *ws)
+{
+ int slave;
+ char *path;
+ pid_t pid;
+
+ if ((*master = open("/dev/ptmx", O_RDWR|O_NOCTTY)) == -1)
+ return (-1);
+ if (grantpt(*master) != 0)
+ goto out;
+ if (unlockpt(*master) != 0)
+ goto out;
+
+ if ((path = ptsname(*master)) == NULL)
+ goto out;
+ if (name != NULL)
+ strlcpy(name, path, TTY_NAME_MAX);
+ if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1)
+ goto out;
+
+ switch (pid = fork()) {
+ case -1:
+ goto out;
+ case 0:
+ close(*master);
+
+ setsid();
+#ifdef TIOCSCTTY
+ if (ioctl(slave, TIOCSCTTY, NULL) == -1)
+ fatal("ioctl failed");
+#endif
+
+ if (ioctl(slave, I_PUSH, "ptem") == -1)
+ fatal("ioctl failed");
+ if (ioctl(slave, I_PUSH, "ldterm") == -1)
+ fatal("ioctl failed");
+
+ if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1)
+ fatal("tcsetattr failed");
+ if (ioctl(slave, TIOCSWINSZ, ws) == -1)
+ fatal("ioctl failed");
+
+ dup2(slave, 0);
+ dup2(slave, 1);
+ dup2(slave, 2);
+ if (slave > 2)
+ close(slave);
+ return (0);
+ }
+
+ close(slave);
+ return (pid);
+
+out:
+ if (*master != -1)
+ close(*master);
+ if (slave != -1)
+ close(slave);
+ return (-1);
+}
diff --git a/compat/getopt.c b/compat/getopt.c
new file mode 100644
index 00000000..38c317cc
--- /dev/null
+++ b/compat/getopt.c
@@ -0,0 +1,116 @@
+/* $Id$ */
+
+/*
+ * 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 "tmux.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 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", __progname, BSDoptopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ BSDoptarg = NULL;
+ if (!*place)
+ ++BSDoptind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ BSDoptarg = 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",
+ __progname, BSDoptopt);
+ return (BADCH);
+ }
+ else /* white space */
+ BSDoptarg = nargv[BSDoptind];
+ place = EMSG;
+ ++BSDoptind;
+ }
+ return (BSDoptopt); /* dump back option letter */
+}
diff --git a/compat/imsg-buffer.c b/compat/imsg-buffer.c
new file mode 100644
index 00000000..24db311d
--- /dev/null
+++ b/compat/imsg-buffer.c
@@ -0,0 +1,303 @@
+/* $Id$ */
+/* $OpenBSD: imsg-buffer.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+int ibuf_realloc(struct ibuf *, size_t);
+void ibuf_enqueue(struct msgbuf *, struct ibuf *);
+void ibuf_dequeue(struct msgbuf *, struct ibuf *);
+
+struct ibuf *
+ibuf_open(size_t len)
+{
+ struct ibuf *buf;
+
+ if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
+ return (NULL);
+ if ((buf->buf = malloc(len)) == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ buf->size = buf->max = len;
+ buf->fd = -1;
+
+ return (buf);
+}
+
+struct ibuf *
+ibuf_dynamic(size_t len, size_t max)
+{
+ struct ibuf *buf;
+
+ if (max < len)
+ return (NULL);
+
+ if ((buf = ibuf_open(len)) == NULL)
+ return (NULL);
+
+ if (max > 0)
+ buf->max = max;
+
+ return (buf);
+}
+
+int
+ibuf_realloc(struct ibuf *buf, size_t len)
+{
+ u_char *b;
+
+ /* on static buffers max is eq size and so the following fails */
+ if (buf->wpos + len > buf->max) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ b = realloc(buf->buf, buf->wpos + len);
+ if (b == NULL)
+ return (-1);
+ buf->buf = b;
+ buf->size = buf->wpos + len;
+
+ return (0);
+}
+
+int
+ibuf_add(struct ibuf *buf, const void *data, size_t len)
+{
+ if (buf->wpos + len > buf->size)
+ if (ibuf_realloc(buf, len) == -1)
+ return (-1);
+
+ memcpy(buf->buf + buf->wpos, data, len);
+ buf->wpos += len;
+ return (0);
+}
+
+void *
+ibuf_reserve(struct ibuf *buf, size_t len)
+{
+ void *b;
+
+ if (buf->wpos + len > buf->size)
+ if (ibuf_realloc(buf, len) == -1)
+ return (NULL);
+
+ b = buf->buf + buf->wpos;
+ buf->wpos += len;
+ return (b);
+}
+
+void *
+ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
+{
+ /* only allowed to seek in already written parts */
+ if (pos + len > buf->wpos)
+ return (NULL);
+
+ return (buf->buf + pos);
+}
+
+size_t
+ibuf_size(struct ibuf *buf)
+{
+ return (buf->wpos);
+}
+
+size_t
+ibuf_left(struct ibuf *buf)
+{
+ return (buf->max - buf->wpos);
+}
+
+void
+ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+ ibuf_enqueue(msgbuf, buf);
+}
+
+int
+ibuf_write(struct msgbuf *msgbuf)
+{
+ struct iovec iov[IOV_MAX];
+ struct ibuf *buf;
+ unsigned int i = 0;
+ ssize_t n;
+
+ bzero(&iov, sizeof(iov));
+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+ if (i >= IOV_MAX)
+ break;
+ iov[i].iov_base = buf->buf + buf->rpos;
+ iov[i].iov_len = buf->wpos - buf->rpos;
+ i++;
+ }
+
+ if ((n = writev(msgbuf->fd, iov, i)) == -1) {
+ if (errno == EAGAIN || errno == ENOBUFS ||
+ errno == EINTR) /* try later */
+ return (0);
+ else
+ return (-1);
+ }
+
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (-2);
+ }
+
+ msgbuf_drain(msgbuf, n);
+
+ return (0);
+}
+
+void
+ibuf_free(struct ibuf *buf)
+{
+ free(buf->buf);
+ free(buf);
+}
+
+void
+msgbuf_init(struct msgbuf *msgbuf)
+{
+ msgbuf->queued = 0;
+ msgbuf->fd = -1;
+ TAILQ_INIT(&msgbuf->bufs);
+}
+
+void
+msgbuf_drain(struct msgbuf *msgbuf, size_t n)
+{
+ struct ibuf *buf, *next;
+
+ for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
+ buf = next) {
+ next = TAILQ_NEXT(buf, entry);
+ if (buf->rpos + n >= buf->wpos) {
+ n -= buf->wpos - buf->rpos;
+ ibuf_dequeue(msgbuf, buf);
+ } else {
+ buf->rpos += n;
+ n = 0;
+ }
+ }
+}
+
+void
+msgbuf_clear(struct msgbuf *msgbuf)
+{
+ struct ibuf *buf;
+
+ while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
+ ibuf_dequeue(msgbuf, buf);
+}
+
+int
+msgbuf_write(struct msgbuf *msgbuf)
+{
+ struct iovec iov[IOV_MAX];
+ struct ibuf *buf;
+ unsigned int i = 0;
+ ssize_t n;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(int))];
+ } cmsgbuf;
+
+ bzero(&iov, sizeof(iov));
+ bzero(&msg, sizeof(msg));
+ TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
+ if (i >= IOV_MAX)
+ break;
+ iov[i].iov_base = buf->buf + buf->rpos;
+ iov[i].iov_len = buf->wpos - buf->rpos;
+ i++;
+ if (buf->fd != -1)
+ break;
+ }
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = i;
+
+ if (buf != NULL && buf->fd != -1) {
+ msg.msg_control = (caddr_t)&cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = buf->fd;
+ }
+
+ if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
+ if (errno == EAGAIN || errno == ENOBUFS ||
+ errno == EINTR) /* try later */
+ return (0);
+ else
+ return (-1);
+ }
+
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (-2);
+ }
+
+ /*
+ * assumption: fd got sent if sendmsg sent anything
+ * this works because fds are passed one at a time
+ */
+ if (buf != NULL && buf->fd != -1) {
+ close(buf->fd);
+ buf->fd = -1;
+ }
+
+ msgbuf_drain(msgbuf, n);
+
+ return (0);
+}
+
+void
+ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+ TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
+ msgbuf->queued++;
+}
+
+void
+ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
+{
+ TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
+
+ if (buf->fd != -1)
+ close(buf->fd);
+
+ msgbuf->queued--;
+ ibuf_free(buf);
+}
diff --git a/compat/imsg.c b/compat/imsg.c
new file mode 100644
index 00000000..0feff660
--- /dev/null
+++ b/compat/imsg.c
@@ -0,0 +1,271 @@
+/* $Id$ */
+/* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+int imsg_get_fd(struct imsgbuf *);
+
+void
+imsg_init(struct imsgbuf *ibuf, int fd)
+{
+ msgbuf_init(&ibuf->w);
+ bzero(&ibuf->r, sizeof(ibuf->r));
+ ibuf->fd = fd;
+ ibuf->w.fd = fd;
+ ibuf->pid = getpid();
+ TAILQ_INIT(&ibuf->fds);
+}
+
+ssize_t
+imsg_read(struct imsgbuf *ibuf)
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(int) * 16)];
+ } cmsgbuf;
+ struct iovec iov;
+ ssize_t n;
+ int fd;
+ struct imsg_fd *ifd;
+
+ bzero(&msg, sizeof(msg));
+
+ 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 ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
+ if (errno != EINTR && errno != EAGAIN) {
+ return (-1);
+ }
+ return (-2);
+ }
+
+ 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) {
+ fd = (*(int *)CMSG_DATA(cmsg));
+ if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL) {
+ close(fd);
+ return (-1);
+ }
+ ifd->fd = fd;
+ TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry);
+ }
+ /* we do not handle other ctl data level */
+ }
+
+ 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);
+
+ 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 ((imsg->data = malloc(datalen)) == NULL && datalen != 0)
+ return (-1);
+
+ if (imsg->hdr.flags & IMSGF_HASFD)
+ imsg->fd = imsg_get_fd(ibuf);
+ else
+ imsg->fd = -1;
+
+ 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_compose(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
+ pid_t pid, int fd, void *data, u_int16_t datalen)
+{
+ struct ibuf *wbuf;
+
+ if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
+ return (-1);
+
+ if (imsg_add(wbuf, data, datalen) == -1)
+ return (-1);
+
+ wbuf->fd = fd;
+
+ imsg_close(ibuf, wbuf);
+
+ return (1);
+}
+
+int
+imsg_composev(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
+ pid_t pid, int fd, const struct iovec *iov, int iovcnt)
+{
+ struct ibuf *wbuf;
+ int i, datalen = 0;
+
+ for (i = 0; i < iovcnt; i++)
+ datalen += iov[i].iov_len;
+
+ 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);
+
+ wbuf->fd = fd;
+
+ imsg_close(ibuf, wbuf);
+
+ return (1);
+}
+
+/* ARGSUSED */
+struct ibuf *
+imsg_create(struct imsgbuf *ibuf, u_int32_t type, u_int32_t peerid,
+ pid_t pid, u_int16_t datalen)
+{
+ struct ibuf *wbuf;
+ struct imsg_hdr hdr;
+
+ datalen += IMSG_HEADER_SIZE;
+ if (datalen > MAX_IMSGSIZE) {
+ errno = ERANGE;
+ return (NULL);
+ }
+
+ hdr.type = type;
+ hdr.flags = 0;
+ hdr.peerid = peerid;
+ if ((hdr.pid = pid) == 0)
+ hdr.pid = ibuf->pid;
+ if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
+ return (NULL);
+ }
+ if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
+ return (NULL);
+
+ return (wbuf);
+}
+
+int
+imsg_add(struct ibuf *msg, void *data, u_int16_t datalen)
+{
+ if (datalen)
+ if (ibuf_add(msg, data, datalen) == -1) {
+ ibuf_free(msg);
+ return (-1);
+ }
+ return (datalen);
+}
+
+void
+imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
+{
+ struct imsg_hdr *hdr;
+
+ hdr = (struct imsg_hdr *)msg->buf;
+
+ hdr->flags &= ~IMSGF_HASFD;
+ if (msg->fd != -1)
+ hdr->flags |= IMSGF_HASFD;
+
+ hdr->len = (u_int16_t)msg->wpos;
+
+ ibuf_close(&ibuf->w, msg);
+}
+
+void
+imsg_free(struct imsg *imsg)
+{
+ free(imsg->data);
+}
+
+int
+imsg_get_fd(struct imsgbuf *ibuf)
+{
+ int fd;
+ struct imsg_fd *ifd;
+
+ if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
+ return (-1);
+
+ fd = ifd->fd;
+ TAILQ_REMOVE(&ibuf->fds, ifd, entry);
+ free(ifd);
+
+ 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);
+}
diff --git a/compat/imsg.h b/compat/imsg.h
new file mode 100644
index 00000000..f8a78e22
--- /dev/null
+++ b/compat/imsg.h
@@ -0,0 +1,110 @@
+/* $Id$ */
+/* $OpenBSD: imsg.h,v 1.4 2010/05/26 13:56:07 nicm Exp $ */
+
+/*
+ * 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>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "tmux.h"
+
+#define IBUF_READ_SIZE 65535
+#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
+#define MAX_IMSGSIZE 16384
+
+struct ibuf {
+ TAILQ_ENTRY(ibuf) entry;
+ u_char *buf;
+ size_t size;
+ size_t max;
+ size_t wpos;
+ size_t rpos;
+ int fd;
+};
+
+struct msgbuf {
+ TAILQ_HEAD(, ibuf) bufs;
+ u_int32_t queued;
+ int fd;
+};
+
+struct ibuf_read {
+ u_char buf[IBUF_READ_SIZE];
+ u_char *rptr;
+ size_t wpos;
+};
+
+struct imsg_fd {
+ TAILQ_ENTRY(imsg_fd) entry;
+ int fd;
+};
+
+struct imsgbuf {
+ TAILQ_HEAD(, imsg_fd) fds;
+ struct ibuf_read r;
+ struct msgbuf w;
+ int fd;
+ pid_t pid;
+};
+
+#define IMSGF_HASFD 1
+
+struct imsg_hdr {
+ u_int32_t type;
+ u_int16_t len;
+ u_int16_t flags;
+ u_int32_t peerid;
+ u_int32_t pid;
+};
+
+struct imsg {
+ struct imsg_hdr hdr;
+ int fd;
+ void *data;
+};
+
+
+/* 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);
+void *ibuf_reserve(struct ibuf *, size_t);
+void *ibuf_seek(struct ibuf *, size_t, size_t);
+size_t ibuf_size(struct ibuf *);
+size_t ibuf_left(struct ibuf *);
+void ibuf_close(struct msgbuf *, struct ibuf *);
+int ibuf_write(struct msgbuf *);
+void ibuf_free(struct ibuf *);
+void msgbuf_init(struct msgbuf *);
+void msgbuf_clear(struct msgbuf *);
+int msgbuf_write(struct msgbuf *);
+void msgbuf_drain(struct msgbuf *, size_t);
+
+/* imsg.c */
+void imsg_init(struct imsgbuf *, int);
+ssize_t imsg_read(struct imsgbuf *);
+ssize_t imsg_get(struct imsgbuf *, struct imsg *);
+int imsg_compose(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+ int, void *, u_int16_t);
+int imsg_composev(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+ int, const struct iovec *, int);
+struct ibuf *imsg_create(struct imsgbuf *, u_int32_t, u_int32_t, pid_t,
+ u_int16_t);
+int imsg_add(struct ibuf *, void *, u_int16_t);
+void imsg_close(struct imsgbuf *, struct ibuf *);
+void imsg_free(struct imsg *);
+int imsg_flush(struct imsgbuf *);
+void imsg_clear(struct imsgbuf *);
diff --git a/compat/queue.h b/compat/queue.h
new file mode 100644
index 00000000..622301d1
--- /dev/null
+++ b/compat/queue.h
@@ -0,0 +1,568 @@
+/* $OpenBSD: queue.h,v 1.36 2012/04/11 13:29:14 naddy Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * 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.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
+#define _Q_INVALIDATE(a) (a) = ((void *)-1)
+#else
+#define _Q_INVALIDATE(a)
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = SLIST_FIRST(head); \
+ (var) != SLIST_END(head); \
+ (var) = SLIST_NEXT(var, field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST(head); \
+ (var) && ((tvar) = SLIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) { \
+ SLIST_FIRST(head) = SLIST_END(head); \
+}
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->slh_first; \
+ \
+ while (curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ _Q_INVALIDATE((elm)->field.sle_next); \
+ } \
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for((var) = LIST_FIRST(head); \
+ (var)!= LIST_END(head); \
+ (var) = LIST_NEXT(var, field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST(head); \
+ (var) && ((tvar) = LIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ LIST_FIRST(head) = LIST_END(head); \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = SIMPLEQ_NEXT(var, field))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * tail queue access methods
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) NULL
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) \
+ (TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field) \
+ for((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV(var, headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue access methods
+ */
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+#define CIRCLEQ_EMPTY(head) \
+ (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for((var) = CIRCLEQ_FIRST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = CIRCLEQ_FIRST(head); \
+ (var) != CIRCLEQ_END(head) && \
+ ((tvar) = CIRCLEQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for((var) = CIRCLEQ_LAST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_PREV(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = CIRCLEQ_LAST(head, headname); \
+ (var) != CIRCLEQ_END(head) && \
+ ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = CIRCLEQ_END(head); \
+ (head)->cqh_last = CIRCLEQ_END(head); \
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
+ if ((head)->cqh_last == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = CIRCLEQ_END(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+ _Q_INVALIDATE((elm)->field.cqe_prev); \
+ _Q_INVALIDATE((elm)->field.cqe_next); \
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
+ CIRCLEQ_END(head)) \
+ (head).cqh_last = (elm2); \
+ else \
+ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
+ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
+ CIRCLEQ_END(head)) \
+ (head).cqh_first = (elm2); \
+ else \
+ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
+ _Q_INVALIDATE((elm)->field.cqe_prev); \
+ _Q_INVALIDATE((elm)->field.cqe_next); \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/compat/setenv.c b/compat/setenv.c
new file mode 100644
index 00000000..43122ba5
--- /dev/null
+++ b/compat/setenv.c
@@ -0,0 +1,49 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2010 Dagobert Michelsen
+ * Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "tmux.h"
+
+int
+setenv(const char *name, const char *value, unused int overwrite)
+{
+ char *newval;
+
+ xasprintf(&newval, "%s=%s", name, value);
+ return (putenv(newval));
+}
+
+int
+unsetenv(const char *name)
+{
+ char **envptr;
+ int namelen;
+
+ namelen = strlen(name);
+ for (envptr = environ; *envptr != NULL; envptr++) {
+ if (strncmp(name, *envptr, namelen) == 0 &&
+ ((*envptr)[namelen] == '=' || (*envptr)[namelen] == '\0'))
+ break;
+ }
+ for (; *envptr != NULL; envptr++)
+ *envptr = *(envptr + 1);
+ return (0);
+}
diff --git a/compat/strcasestr.c b/compat/strcasestr.c
new file mode 100644
index 00000000..5e03bbb0
--- /dev/null
+++ b/compat/strcasestr.c
@@ -0,0 +1,61 @@
+/* $Id$ */
+/* $OpenBSD: strcasestr.c,v 1.3 2006/03/31 05:34:55 deraadt Exp $ */
+/* $NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+char *
+strcasestr(const char *s, const char *find)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != 0) {
+ c = (char)tolower((unsigned char)c);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while ((char)tolower((unsigned char)sc) != c);
+ } while (strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
diff --git a/compat/strlcat.c b/compat/strlcat.c
new file mode 100644
index 00000000..1ba236e2
--- /dev/null
+++ b/compat/strlcat.c
@@ -0,0 +1,58 @@
+/* $Id$ */
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
+
+/*
+ * Copyright (c) 1998 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.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include "tmux.h"
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/compat/strlcpy.c b/compat/strlcpy.c
new file mode 100644
index 00000000..80e13a8f
--- /dev/null
+++ b/compat/strlcpy.c
@@ -0,0 +1,54 @@
+/* $Id$ */
+/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
+
+/*
+ * Copyright (c) 1998 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.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include "tmux.h"
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/compat/strsep.c b/compat/strsep.c
new file mode 100644
index 00000000..0a7aa328
--- /dev/null
+++ b/compat/strsep.c
@@ -0,0 +1,72 @@
+/* $Id$ */
+/* $OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(char **stringp, const char *delim)
+{
+ char *s;
+ const char *spanp;
+ int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/compat/strtonum.c b/compat/strtonum.c
new file mode 100644
index 00000000..860e5508
--- /dev/null
+++ b/compat/strtonum.c
@@ -0,0 +1,68 @@
+/* $Id$ */
+/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
+
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "tmux.h"
+
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+ const char **errstrp)
+{
+ long long ll = 0;
+ char *ep;
+ int error = 0;
+ struct errval {
+ const char *errstr;
+ int err;
+ } ev[4] = {
+ { NULL, 0 },
+ { "invalid", EINVAL },
+ { "too small", ERANGE },
+ { "too large", ERANGE },
+ };
+
+ ev[0].err = errno;
+ errno = 0;
+ if (minval > maxval)
+ error = INVALID;
+ else {
+ ll = strtoll(numstr, &ep, 10);
+ if (numstr == ep || *ep != '\0')
+ error = INVALID;
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+ error = TOOSMALL;
+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+ error = TOOLARGE;
+ }
+ if (errstrp != NULL)
+ *errstrp = ev[error].errstr;
+ errno = ev[error].err;
+ if (error)
+ ll = 0;
+
+ return (ll);
+}
diff --git a/compat/tree.h b/compat/tree.h
new file mode 100644
index 00000000..73041340
--- /dev/null
+++ b/compat/tree.h
@@ -0,0 +1,749 @@
+/* $Id$ */
+/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */
+/*
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#ifndef _SYS_TREE_H_
+#define _SYS_TREE_H_
+
+/*
+ * This file defines data structures for different types of trees:
+ * splay trees and red-black trees.
+ *
+ * A splay tree is a self-organizing data structure. Every operation
+ * on the tree causes a splay to happen. The splay moves the requested
+ * node to the root of the tree and partly rebalances it.
+ *
+ * This has the benefit that request locality causes faster lookups as
+ * the requested nodes move to the top of the tree. On the other hand,
+ * every lookup causes memory writes.
+ *
+ * The Balance Theorem bounds the total access time for m operations
+ * and n inserts on an initially empty tree as O((m + n)lg n). The
+ * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
+ *
+ * A red-black tree is a binary search tree with the node color as an
+ * extra attribute. It fulfills a set of conditions:
+ * - every search path from the root to a leaf consists of the
+ * same number of black nodes,
+ * - each red node (except for the root) has a black parent,
+ * - each leaf node is black.
+ *
+ * Every operation on a red-black tree is bounded as O(lg n).
+ * The maximum height of a red-black tree is 2lg (n+1).
+ */
+
+#define SPLAY_HEAD(name, type) \
+struct name { \
+ struct type *sph_root; /* root of the tree */ \
+}
+
+#define SPLAY_INITIALIZER(root) \
+ { NULL }
+
+#define SPLAY_INIT(root) do { \
+ (root)->sph_root = NULL; \
+} while (0)
+
+#define SPLAY_ENTRY(type) \
+struct { \
+ struct type *spe_left; /* left element */ \
+ struct type *spe_right; /* right element */ \
+}
+
+#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
+#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
+#define SPLAY_ROOT(head) (head)->sph_root
+#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
+
+/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
+#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (0)
+
+#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (0)
+
+#define SPLAY_LINKLEFT(head, tmp, field) do { \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
+} while (0)
+
+#define SPLAY_LINKRIGHT(head, tmp, field) do { \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
+} while (0)
+
+#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
+ SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
+ SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
+} while (0)
+
+/* Generates prototypes and inline functions */
+
+#define SPLAY_PROTOTYPE(name, type, field, cmp) \
+void name##_SPLAY(struct name *, struct type *); \
+void name##_SPLAY_MINMAX(struct name *, int); \
+struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
+struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
+ \
+/* Finds the node with the same key as elm */ \
+static __inline struct type * \
+name##_SPLAY_FIND(struct name *head, struct type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) \
+ return(NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) \
+ return (head->sph_root); \
+ return (NULL); \
+} \
+ \
+static __inline struct type * \
+name##_SPLAY_NEXT(struct name *head, struct type *elm) \
+{ \
+ name##_SPLAY(head, elm); \
+ if (SPLAY_RIGHT(elm, field) != NULL) { \
+ elm = SPLAY_RIGHT(elm, field); \
+ while (SPLAY_LEFT(elm, field) != NULL) { \
+ elm = SPLAY_LEFT(elm, field); \
+ } \
+ } else \
+ elm = NULL; \
+ return (elm); \
+} \
+ \
+static __inline struct type * \
+name##_SPLAY_MIN_MAX(struct name *head, int val) \
+{ \
+ name##_SPLAY_MINMAX(head, val); \
+ return (SPLAY_ROOT(head)); \
+}
+
+/* Main splay operation.
+ * Moves node close to the key of elm to top
+ */
+#define SPLAY_GENERATE(name, type, field, cmp) \
+struct type * \
+name##_SPLAY_INSERT(struct name *head, struct type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) { \
+ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
+ } else { \
+ int __comp; \
+ name##_SPLAY(head, elm); \
+ __comp = (cmp)(elm, (head)->sph_root); \
+ if(__comp < 0) { \
+ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
+ SPLAY_RIGHT(elm, field) = (head)->sph_root; \
+ SPLAY_LEFT((head)->sph_root, field) = NULL; \
+ } else if (__comp > 0) { \
+ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT(elm, field) = (head)->sph_root; \
+ SPLAY_RIGHT((head)->sph_root, field) = NULL; \
+ } else \
+ return ((head)->sph_root); \
+ } \
+ (head)->sph_root = (elm); \
+ return (NULL); \
+} \
+ \
+struct type * \
+name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
+{ \
+ struct type *__tmp; \
+ if (SPLAY_EMPTY(head)) \
+ return (NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) { \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
+ } else { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
+ name##_SPLAY(head, elm); \
+ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
+ } \
+ return (elm); \
+ } \
+ return (NULL); \
+} \
+ \
+void \
+name##_SPLAY(struct name *head, struct type *elm) \
+{ \
+ struct type __node, *__left, *__right, *__tmp; \
+ int __comp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while ((__comp = (cmp)(elm, (head)->sph_root))) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) > 0){ \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+} \
+ \
+/* Splay with either the minimum or the maximum element \
+ * Used to find minimum or maximum element in tree. \
+ */ \
+void name##_SPLAY_MINMAX(struct name *head, int __comp) \
+{ \
+ struct type __node, *__left, *__right, *__tmp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while (1) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp > 0) { \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+}
+
+#define SPLAY_NEGINF -1
+#define SPLAY_INF 1
+
+#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
+#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
+#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
+#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
+#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
+#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
+
+#define SPLAY_FOREACH(x, name, head) \
+ for ((x) = SPLAY_MIN(name, head); \
+ (x) != NULL; \
+ (x) = SPLAY_NEXT(name, head, x))
+
+/* Macros that define a red-black tree */
+#define RB_HEAD(name, type) \
+struct name { \
+ struct type *rbh_root; /* root of the tree */ \
+}
+
+#define RB_INITIALIZER(root) \
+ { NULL }
+
+#define RB_INIT(root) do { \
+ (root)->rbh_root = NULL; \
+} while (0)
+
+#define RB_BLACK 0
+#define RB_RED 1
+#define RB_ENTRY(type) \
+struct { \
+ struct type *rbe_left; /* left element */ \
+ struct type *rbe_right; /* right element */ \
+ struct type *rbe_parent; /* parent element */ \
+ int rbe_color; /* node color */ \
+}
+
+#define RB_LEFT(elm, field) (elm)->field.rbe_left
+#define RB_RIGHT(elm, field) (elm)->field.rbe_right
+#define RB_PARENT(elm, field) (elm)->field.rbe_parent
+#define RB_COLOR(elm, field) (elm)->field.rbe_color
+#define RB_ROOT(head) (head)->rbh_root
+#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
+
+#define RB_SET(elm, parent, field) do { \
+ RB_PARENT(elm, field) = parent; \
+ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
+ RB_COLOR(elm, field) = RB_RED; \
+} while (0)
+
+#define RB_SET_BLACKRED(black, red, field) do { \
+ RB_COLOR(black, field) = RB_BLACK; \
+ RB_COLOR(red, field) = RB_RED; \
+} while (0)
+
+#ifndef RB_AUGMENT
+#define RB_AUGMENT(x) do {} while (0)
+#endif
+
+#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
+ (tmp) = RB_RIGHT(elm, field); \
+ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
+ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_LEFT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (0)
+
+#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
+ (tmp) = RB_LEFT(elm, field); \
+ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
+ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_RIGHT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (0)
+
+/* Generates prototypes and inline functions */
+#define RB_PROTOTYPE(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
+attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
+attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
+attr struct type *name##_RB_INSERT(struct name *, struct type *); \
+attr struct type *name##_RB_FIND(struct name *, struct type *); \
+attr struct type *name##_RB_NFIND(struct name *, struct type *); \
+attr struct type *name##_RB_NEXT(struct type *); \
+attr struct type *name##_RB_PREV(struct type *); \
+attr struct type *name##_RB_MINMAX(struct name *, int); \
+ \
+
+/* Main rb operation.
+ * Moves node close to the key of elm to top
+ */
+#define RB_GENERATE(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define RB_GENERATE_STATIC(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
+attr void \
+name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
+{ \
+ struct type *parent, *gparent, *tmp; \
+ while ((parent = RB_PARENT(elm, field)) && \
+ RB_COLOR(parent, field) == RB_RED) { \
+ gparent = RB_PARENT(parent, field); \
+ if (parent == RB_LEFT(gparent, field)) { \
+ tmp = RB_RIGHT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_RIGHT(parent, field) == elm) { \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_RIGHT(head, gparent, tmp, field); \
+ } else { \
+ tmp = RB_LEFT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_LEFT(parent, field) == elm) { \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_LEFT(head, gparent, tmp, field); \
+ } \
+ } \
+ RB_COLOR(head->rbh_root, field) = RB_BLACK; \
+} \
+ \
+attr void \
+name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
+{ \
+ struct type *tmp; \
+ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
+ elm != RB_ROOT(head)) { \
+ if (RB_LEFT(parent, field) == elm) { \
+ tmp = RB_RIGHT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
+ struct type *oleft; \
+ if ((oleft = RB_LEFT(tmp, field)))\
+ RB_COLOR(oleft, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_RIGHT(head, tmp, oleft, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_RIGHT(tmp, field)) \
+ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ elm = RB_ROOT(head); \
+ break; \
+ } \
+ } else { \
+ tmp = RB_LEFT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
+ struct type *oright; \
+ if ((oright = RB_RIGHT(tmp, field)))\
+ RB_COLOR(oright, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_LEFT(head, tmp, oright, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_LEFT(tmp, field)) \
+ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ elm = RB_ROOT(head); \
+ break; \
+ } \
+ } \
+ } \
+ if (elm) \
+ RB_COLOR(elm, field) = RB_BLACK; \
+} \
+ \
+attr struct type * \
+name##_RB_REMOVE(struct name *head, struct type *elm) \
+{ \
+ struct type *child, *parent, *old = elm; \
+ int color; \
+ if (RB_LEFT(elm, field) == NULL) \
+ child = RB_RIGHT(elm, field); \
+ else if (RB_RIGHT(elm, field) == NULL) \
+ child = RB_LEFT(elm, field); \
+ else { \
+ struct type *left; \
+ elm = RB_RIGHT(elm, field); \
+ while ((left = RB_LEFT(elm, field))) \
+ elm = left; \
+ child = RB_RIGHT(elm, field); \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = child; \
+ if (RB_PARENT(elm, field) == old) \
+ parent = elm; \
+ (elm)->field = (old)->field; \
+ if (RB_PARENT(old, field)) { \
+ if (RB_LEFT(RB_PARENT(old, field), field) == old)\
+ RB_LEFT(RB_PARENT(old, field), field) = elm;\
+ else \
+ RB_RIGHT(RB_PARENT(old, field), field) = elm;\
+ RB_AUGMENT(RB_PARENT(old, field)); \
+ } else \
+ RB_ROOT(head) = elm; \
+ RB_PARENT(RB_LEFT(old, field), field) = elm; \
+ if (RB_RIGHT(old, field)) \
+ RB_PARENT(RB_RIGHT(old, field), field) = elm; \
+ if (parent) { \
+ left = parent; \
+ do { \
+ RB_AUGMENT(left); \
+ } while ((left = RB_PARENT(left, field))); \
+ } \
+ goto color; \
+ } \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = child; \
+color: \
+ if (color == RB_BLACK) \
+ name##_RB_REMOVE_COLOR(head, parent, child); \
+ return (old); \
+} \
+ \
+/* Inserts a node into the RB tree */ \
+attr struct type * \
+name##_RB_INSERT(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp; \
+ struct type *parent = NULL; \
+ int comp = 0; \
+ tmp = RB_ROOT(head); \
+ while (tmp) { \
+ parent = tmp; \
+ comp = (cmp)(elm, parent); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ RB_SET(elm, parent, field); \
+ if (parent != NULL) { \
+ if (comp < 0) \
+ RB_LEFT(parent, field) = elm; \
+ else \
+ RB_RIGHT(parent, field) = elm; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT(head) = elm; \
+ name##_RB_INSERT_COLOR(head, elm); \
+ return (NULL); \
+} \
+ \
+/* Finds the node with the same key as elm */ \
+attr struct type * \
+name##_RB_FIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (NULL); \
+} \
+ \
+/* Finds the first node greater than or equal to the search key */ \
+attr struct type * \
+name##_RB_NFIND(struct name *head, struct type *elm) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *res = NULL; \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) { \
+ res = tmp; \
+ tmp = RB_LEFT(tmp, field); \
+ } \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (res); \
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_NEXT(struct type *elm) \
+{ \
+ if (RB_RIGHT(elm, field)) { \
+ elm = RB_RIGHT(elm, field); \
+ while (RB_LEFT(elm, field)) \
+ elm = RB_LEFT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+/* ARGSUSED */ \
+attr struct type * \
+name##_RB_PREV(struct type *elm) \
+{ \
+ if (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ while (RB_RIGHT(elm, field)) \
+ elm = RB_RIGHT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+attr struct type * \
+name##_RB_MINMAX(struct name *head, int val) \
+{ \
+ struct type *tmp = RB_ROOT(head); \
+ struct type *parent = NULL; \
+ while (tmp) { \
+ parent = tmp; \
+ if (val < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else \
+ tmp = RB_RIGHT(tmp, field); \
+ } \
+ return (parent); \
+}
+
+#define RB_NEGINF -1
+#define RB_INF 1
+
+#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
+#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
+#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
+#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
+#define RB_PREV(name, x, y) name##_RB_PREV(y)
+#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
+#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
+
+#define RB_FOREACH(x, name, head) \
+ for ((x) = RB_MIN(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_NEXT(x))
+
+#define RB_FOREACH_SAFE(x, name, head, y) \
+ for ((x) = RB_MIN(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE(x, name, head) \
+ for ((x) = RB_MAX(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_PREV(x))
+
+#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
+ for ((x) = RB_MAX(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \
+ (x) = (y))
+
+#endif /* _SYS_TREE_H_ */
diff --git a/compat/unvis.c b/compat/unvis.c
new file mode 100644
index 00000000..874b2275
--- /dev/null
+++ b/compat/unvis.c
@@ -0,0 +1,282 @@
+/* $Id$ */
+/* $OpenBSD: unvis.c,v 1.12 2005/08/08 08:05:34 espie Exp $ */
+/*-
+ * Copyright (c) 1989, 1993
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+
+#include "tmux.h"
+
+/*
+ * decode driven by state machine
+ */
+#define S_GROUND 0 /* haven't seen escape char */
+#define S_START 1 /* start decoding special sequence */
+#define S_META 2 /* metachar started (M) */
+#define S_META1 3 /* metachar more, regular char (-) */
+#define S_CTRL 4 /* control char started (^) */
+#define S_OCTAL2 5 /* octal digit 2 */
+#define S_OCTAL3 6 /* octal digit 3 */
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+
+/*
+ * unvis - decode characters previously encoded by vis
+ */
+int
+unvis(char *cp, char c, int *astate, int flag)
+{
+
+ if (flag & UNVIS_END) {
+ if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ }
+ return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
+ }
+
+ switch (*astate) {
+
+ case S_GROUND:
+ *cp = 0;
+ if (c == '\\') {
+ *astate = S_START;
+ return (0);
+ }
+ *cp = c;
+ return (UNVIS_VALID);
+
+ case S_START:
+ switch(c) {
+ case '\\':
+ *cp = c;
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ *cp = (c - '0');
+ *astate = S_OCTAL2;
+ return (0);
+ case 'M':
+ *cp = (char) 0200;
+ *astate = S_META;
+ return (0);
+ case '^':
+ *astate = S_CTRL;
+ return (0);
+ case 'n':
+ *cp = '\n';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'r':
+ *cp = '\r';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'b':
+ *cp = '\b';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'a':
+ *cp = '\007';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'v':
+ *cp = '\v';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 't':
+ *cp = '\t';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'f':
+ *cp = '\f';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 's':
+ *cp = ' ';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'E':
+ *cp = '\033';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case '\n':
+ /*
+ * hidden newline
+ */
+ *astate = S_GROUND;
+ return (UNVIS_NOCHAR);
+ case '$':
+ /*
+ * hidden marker
+ */
+ *astate = S_GROUND;
+ return (UNVIS_NOCHAR);
+ }
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+
+ case S_META:
+ if (c == '-')
+ *astate = S_META1;
+ else if (c == '^')
+ *astate = S_CTRL;
+ else {
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+ }
+ return (0);
+
+ case S_META1:
+ *astate = S_GROUND;
+ *cp |= c;
+ return (UNVIS_VALID);
+
+ case S_CTRL:
+ if (c == '?')
+ *cp |= 0177;
+ else
+ *cp |= c & 037;
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+
+ case S_OCTAL2: /* second possible octal digit */
+ if (isoctal(c)) {
+ /*
+ * yes - and maybe a third
+ */
+ *cp = (*cp << 3) + (c - '0');
+ *astate = S_OCTAL3;
+ return (0);
+ }
+ /*
+ * no - done with current sequence, push back passed char
+ */
+ *astate = S_GROUND;
+ return (UNVIS_VALIDPUSH);
+
+ case S_OCTAL3: /* third possible octal digit */
+ *astate = S_GROUND;
+ if (isoctal(c)) {
+ *cp = (*cp << 3) + (c - '0');
+ return (UNVIS_VALID);
+ }
+ /*
+ * we were done, push back passed char
+ */
+ return (UNVIS_VALIDPUSH);
+
+ default:
+ /*
+ * decoder in unknown state - (probably uninitialized)
+ */
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+ }
+}
+
+/*
+ * strunvis - decode src into dst
+ *
+ * Number of chars decoded into dst is returned, -1 on error.
+ * Dst is null terminated.
+ */
+
+int
+strunvis(char *dst, const char *src)
+{
+ char c;
+ char *start = dst;
+ int state = 0;
+
+ while ((c = *src++)) {
+ again:
+ switch (unvis(dst, c, &state, 0)) {
+ case UNVIS_VALID:
+ dst++;
+ break;
+ case UNVIS_VALIDPUSH:
+ dst++;
+ goto again;
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ default:
+ *dst = '\0';
+ return (-1);
+ }
+ }
+ if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
+ dst++;
+ *dst = '\0';
+ return (dst - start);
+}
+
+ssize_t
+strnunvis(char *dst, const char *src, size_t sz)
+{
+ char c, p;
+ char *start = dst, *end = dst + sz - 1;
+ int state = 0;
+
+ if (sz > 0)
+ *end = '\0';
+ while ((c = *src++)) {
+ again:
+ switch (unvis(&p, c, &state, 0)) {
+ case UNVIS_VALID:
+ if (dst < end)
+ *dst = p;
+ dst++;
+ break;
+ case UNVIS_VALIDPUSH:
+ if (dst < end)
+ *dst = p;
+ dst++;
+ goto again;
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ default:
+ if (dst <= end)
+ *dst = '\0';
+ return (-1);
+ }
+ }
+ if (unvis(&p, c, &state, UNVIS_END) == UNVIS_VALID) {
+ if (dst < end)
+ *dst = p;
+ dst++;
+ }
+ if (dst <= end)
+ *dst = '\0';
+ return (dst - start);
+}
+
diff --git a/compat/vis.c b/compat/vis.c
new file mode 100644
index 00000000..da4ac7cd
--- /dev/null
+++ b/compat/vis.c
@@ -0,0 +1,221 @@
+/* $Id$ */
+/* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */
+/*-
+ * Copyright (c) 1989, 1993
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "tmux.h"
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define isvisible(c) \
+ (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \
+ (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \
+ (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \
+ ((flag & VIS_SP) == 0 && (c) == ' ') || \
+ ((flag & VIS_TAB) == 0 && (c) == '\t') || \
+ ((flag & VIS_NL) == 0 && (c) == '\n') || \
+ ((flag & VIS_SAFE) && ((c) == '\b' || \
+ (c) == '\007' || (c) == '\r' || \
+ isgraph((u_char)(c)))))
+
+/*
+ * vis - visually encode characters
+ */
+char *
+vis(char *dst, int c, int flag, int nextc)
+{
+ if (isvisible(c)) {
+ *dst++ = c;
+ if (c == '\\' && (flag & VIS_NOSLASH) == 0)
+ *dst++ = '\\';
+ *dst = '\0';
+ return (dst);
+ }
+
+ if (flag & VIS_CSTYLE) {
+ switch(c) {
+ case '\n':
+ *dst++ = '\\';
+ *dst++ = 'n';
+ goto done;
+ case '\r':
+ *dst++ = '\\';
+ *dst++ = 'r';
+ goto done;
+ case '\b':
+ *dst++ = '\\';
+ *dst++ = 'b';
+ goto done;
+ case '\a':
+ *dst++ = '\\';
+ *dst++ = 'a';
+ goto done;
+ case '\v':
+ *dst++ = '\\';
+ *dst++ = 'v';
+ goto done;
+ case '\t':
+ *dst++ = '\\';
+ *dst++ = 't';
+ goto done;
+ case '\f':
+ *dst++ = '\\';
+ *dst++ = 'f';
+ goto done;
+ case ' ':
+ *dst++ = '\\';
+ *dst++ = 's';
+ goto done;
+ case '\0':
+ *dst++ = '\\';
+ *dst++ = '0';
+ if (isoctal(nextc)) {
+ *dst++ = '0';
+ *dst++ = '0';
+ }
+ goto done;
+ }
+ }
+ if (((c & 0177) == ' ') || (flag & VIS_OCTAL) ||
+ ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) {
+ *dst++ = '\\';
+ *dst++ = ((u_char)c >> 6 & 07) + '0';
+ *dst++ = ((u_char)c >> 3 & 07) + '0';
+ *dst++ = ((u_char)c & 07) + '0';
+ goto done;
+ }
+ if ((flag & VIS_NOSLASH) == 0)
+ *dst++ = '\\';
+ if (c & 0200) {
+ c &= 0177;
+ *dst++ = 'M';
+ }
+ if (iscntrl((u_char)c)) {
+ *dst++ = '^';
+ if (c == 0177)
+ *dst++ = '?';
+ else
+ *dst++ = c + '@';
+ } else {
+ *dst++ = '-';
+ *dst++ = c;
+ }
+done:
+ *dst = '\0';
+ return (dst);
+}
+
+/*
+ * strvis, strnvis, strvisx - visually encode characters from src into dst
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NULL,
+ * is returned.
+ *
+ * Strnvis will write no more than siz-1 bytes (and will NULL terminate).
+ * The number of bytes needed to fully encode the string is returned.
+ *
+ * Strvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+int
+strvis(char *dst, const char *src, int flag)
+{
+ char c;
+ char *start;
+
+ for (start = dst; (c = *src);)
+ dst = vis(dst, c, flag, *++src);
+ *dst = '\0';
+ return (dst - start);
+}
+
+int
+strnvis(char *dst, const char *src, size_t siz, int flag)
+{
+ char *start, *end;
+ char tbuf[5];
+ int c, i;
+
+ i = 0;
+ for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
+ if (isvisible(c)) {
+ i = 1;
+ *dst++ = c;
+ if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
+ /* need space for the extra '\\' */
+ if (dst < end)
+ *dst++ = '\\';
+ else {
+ dst--;
+ i = 2;
+ break;
+ }
+ }
+ src++;
+ } else {
+ i = vis(tbuf, c, flag, *++src) - tbuf;
+ if (dst + i <= end) {
+ memcpy(dst, tbuf, i);
+ dst += i;
+ } else {
+ src--;
+ break;
+ }
+ }
+ }
+ if (siz > 0)
+ *dst = '\0';
+ if (dst + i > end) {
+ /* adjust return value for truncation */
+ while ((c = *src))
+ dst += vis(tbuf, c, flag, *++src) - tbuf;
+ }
+ return (dst - start);
+}
+
+int
+strvisx(char *dst, const char *src, size_t len, int flag)
+{
+ char c;
+ char *start;
+
+ for (start = dst; len > 1; len--) {
+ c = *src;
+ dst = vis(dst, c, flag, *++src);
+ }
+ if (len)
+ dst = vis(dst, *src, flag, '\0');
+ *dst = '\0';
+ return (dst - start);
+}
diff --git a/compat/vis.h b/compat/vis.h
new file mode 100644
index 00000000..e43e9adc
--- /dev/null
+++ b/compat/vis.h
@@ -0,0 +1,83 @@
+/* $Id$ */
+/* $OpenBSD: vis.h,v 1.11 2005/08/09 19:38:31 millert Exp $ */
+/* $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990 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.
+ *
+ * @(#)vis.h 5.9 (Berkeley) 4/3/91
+ */
+
+#ifndef _VIS_H_
+#define _VIS_H_
+
+/*
+ * to select alternate encoding format
+ */
+#define VIS_OCTAL 0x01 /* use octal \ddd format */
+#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define VIS_SP 0x04 /* also encode space */
+#define VIS_TAB 0x08 /* also encode tab */
+#define VIS_NL 0x10 /* also encode newline */
+#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
+#define VIS_SAFE 0x20 /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define VIS_NOSLASH 0x40 /* inhibit printing '\' */
+#define VIS_GLOB 0x100 /* encode glob(3) magics and '#' */
+
+/*
+ * unvis return codes
+ */
+#define UNVIS_VALID 1 /* character valid */
+#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
+#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
+#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
+#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define UNVIS_END 1 /* no more characters */
+
+char *vis(char *, int, int, int);
+int strvis(char *, const char *, int);
+int strnvis(char *, const char *, size_t, int);
+int strvisx(char *, const char *, size_t, int);
+int strunvis(char *, const char *);
+int unvis(char *, char, int *, int);
+ssize_t strnunvis(char *, const char *, size_t);
+
+#endif /* !_VIS_H_ */
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 00000000..9e060df7
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,481 @@
+# $Id$
+
+# Miscellaneous autofoo bullshit.
+AC_INIT(tmux, 1.8)
+
+AC_CONFIG_AUX_DIR(etc)
+AM_INIT_AUTOMAKE([foreign])
+
+AC_CANONICAL_HOST
+
+# When CFLAGS isn't set at this stage and gcc is detected by the macro below,
+# autoconf will automatically use CFLAGS="-O2 -g". Prevent that by using an
+# empty default.
+: ${CFLAGS=""}
+
+# Set up the compiler in two different ways and say yes we may want to install.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_INSTALL
+
+# Check for various headers. Alternatives included from compat.h.
+AC_CHECK_HEADERS(
+ [ \
+ bitstring.h \
+ curses.h \
+ dirent.h \
+ fcntl.h \
+ inttypes.h \
+ libutil.h \
+ ncurses.h \
+ ndir.h \
+ paths.h \
+ pty.h \
+ stdint.h \
+ sys/dir.h \
+ sys/ndir.h \
+ sys/tree.h \
+ term.h \
+ util.h \
+ ]
+)
+
+# Is this a debug build?
+found_debug=yes
+AC_ARG_ENABLE(
+ debug,
+ AC_HELP_STRING(--enable-debug, create a debug build),
+ found_debug=$enable_debug
+)
+AM_CONDITIONAL(IS_DEBUG, test "x$found_debug" = xyes)
+
+# Is this a static build?
+AC_ARG_ENABLE(
+ static,
+ AC_HELP_STRING(--enable-static, create a static build),
+ found_static=$enable_static
+)
+if test "x$found_static" = xyes; then
+ LDFLAGS="$LDFLAGS -static"
+fi
+
+# Is this gcc?
+AM_CONDITIONAL(IS_GCC, test "x$GCC" = xyes)
+AC_MSG_CHECKING(for gcc that whines about -I)
+AC_EGREP_CPP(
+ yes,
+ [
+ #if __GNUC__ > 3
+ yes
+ #endif
+ ],
+ found_gcc4=yes,
+ found_gcc4=no
+)
+AM_CONDITIONAL(IS_GCC4, test "x$found_gcc4" = xyes)
+AC_MSG_RESULT($found_gcc4)
+
+# Is this Sun CC?
+AC_EGREP_CPP(
+ yes,
+ [
+ #ifdef __SUNPRO_C
+ yes
+ #endif
+ ],
+ found_suncc=yes,
+ found_suncc=no
+)
+AM_CONDITIONAL(IS_SUNCC, test "x$found_suncc" = xyes)
+
+# Is this glibc?
+AC_MSG_CHECKING(for glibc)
+AC_EGREP_CPP(
+ yes,
+ [
+ #include <features.h>
+ #ifdef __GLIBC__
+ yes
+ #endif
+ ],
+ found_glibc=yes,
+ found_glibc=no
+)
+AM_CONDITIONAL(IS_GLIBC, test "x$found_glibc" = xyes)
+AC_MSG_RESULT($found_glibc)
+
+# Look for clock_gettime. Must come before event_init.
+AC_SEARCH_LIBS(clock_gettime, rt)
+
+# Look for libevent.
+PKG_CHECK_MODULES(
+ LIBEVENT,
+ libevent,
+ [
+ CPPFLAGS="$LIBEVENT_CFLAGS $CPPFLAGS"
+ LIBS="$LIBEVENT_LIBS $LIBS"
+ found_libevent=yes
+ ],
+ [
+ AC_SEARCH_LIBS(
+ event_init,
+ [event event-1.4 event2],
+ found_libevent=yes,
+ found_libevent=no
+ )
+ ]
+)
+if test "x$found_libevent" = xno; then
+ AC_MSG_ERROR("libevent not found")
+fi
+
+# Look for curses.
+AC_SEARCH_LIBS(
+ setupterm,
+ [terminfo curses ncurses],
+ found_curses=yes,
+ found_curses=no
+)
+if test "x$found_curses" = xno; then
+ AC_MSG_ERROR("curses not found")
+fi
+
+# Check for b64_ntop.
+AC_MSG_CHECKING(for b64_ntop)
+AC_TRY_LINK(
+ [
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <resolv.h>
+ ],
+ [b64_ntop(NULL, 0, NULL, 0);],
+ found_b64_ntop=yes,
+ found_b64_ntop=no
+)
+if test "x$found_b64_ntop" = xno; then
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING(for b64_ntop with -lresolv)
+ LIBS="$LIBS -lresolv"
+ AC_TRY_LINK(
+ [
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <resolv.h>
+ ],
+ [b64_ntop(NULL, 0, NULL, 0);],
+ found_b64_ntop=yes,
+ found_b64_ntop=no
+ )
+ if test "x$found_b64_ntop" = xno; then
+ AC_MSG_RESULT(no)
+ fi
+fi
+if test "x$found_b64_ntop" = xyes; then
+ AC_DEFINE(HAVE_B64_NTOP)
+ AC_MSG_RESULT(yes)
+fi
+AM_CONDITIONAL(NO_B64_NTOP, [test "x$found_b64_ntop" = xno])
+
+# Look for networking libraries.
+AC_SEARCH_LIBS(inet_ntoa, nsl)
+AC_SEARCH_LIBS(socket, socket)
+AC_CHECK_LIB(xnet, socket)
+
+# Check for CMSG_DATA. Some platforms require _XOPEN_SOURCE_EXTENDED (for
+# example see xopen_networking(7) on HP-UX).
+XOPEN_DEFINES=
+AC_MSG_CHECKING(for CMSG_DATA)
+AC_EGREP_CPP(
+ yes,
+ [
+ #include <sys/socket.h>
+ #ifdef CMSG_DATA
+ yes
+ #endif
+ ],
+ found_cmsg_data=yes,
+ found_cmsg_data=no
+)
+AC_MSG_RESULT($found_cmsg_data)
+if test "x$found_cmsg_data" = xno; then
+ AC_MSG_CHECKING(if CMSG_DATA needs _XOPEN_SOURCE_EXTENDED)
+ AC_EGREP_CPP(
+ yes,
+ [
+ #define _XOPEN_SOURCE 1
+ #define _XOPEN_SOURCE_EXTENDED 1
+ #include <sys/socket.h>
+ #ifdef CMSG_DATA
+ yes
+ #endif
+ ],
+ found_cmsg_data=yes,
+ found_cmsg_data=no
+ )
+ AC_MSG_RESULT($found_cmsg_data)
+ if test "x$found_cmsg_data" = xyes; then
+ XOPEN_DEFINES="-D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED"
+ else
+ AC_MSG_ERROR("CMSG_DATA not found")
+ fi
+fi
+AC_SUBST(XOPEN_DEFINES)
+
+# Look for imsg in libutil. compat/imsg.c is linked by Makefile.am if missing.
+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)
+fi
+AM_CONDITIONAL(NO_IMSG, [test "x$found_imsg_init" = xno])
+
+# Look for forkpty in libutil. compat/forkpty-*.c is linked if not found.
+AC_SEARCH_LIBS(forkpty, util, found_forkpty=yes, found_forkpty=no)
+if test "x$found_forkpty" = xyes; then
+ AC_DEFINE(HAVE_FORKPTY)
+fi
+AM_CONDITIONAL(NO_FORKPTY, [test "x$found_forkpty" = xno])
+
+# Look for closefrom, compat/closefrom.c used if missing.
+AC_CHECK_FUNC(closefrom, found_closefrom=yes, found_closefrom=no)
+if test "x$found_closefrom" = xyes; then
+ AC_DEFINE(HAVE_CLOSEFROM)
+fi
+AM_CONDITIONAL(NO_CLOSEFROM, [test "x$found_closefrom" = xno])
+
+# Look for daemon, compat/daemon.c used if missing.
+AC_CHECK_FUNC(daemon, found_daemon=yes, found_daemon=no)
+if test "x$found_daemon" = xyes; then
+ AC_DEFINE(HAVE_DAEMON)
+fi
+AM_CONDITIONAL(NO_DAEMON, [test "x$found_daemon" = xno])
+
+# Look for setenv, compat/setenv.c used if missing.
+AC_CHECK_FUNC(setenv, found_setenv=yes, found_setenv=no)
+if test "x$found_setenv" = xyes; then
+ AC_DEFINE(HAVE_SETENV)
+fi
+AM_CONDITIONAL(NO_SETENV, [test "x$found_setenv" = xno])
+
+# Look for strlcpy, compat/strlcpy.c used if missing.
+AC_CHECK_FUNC(strlcpy, found_strlcpy=yes, found_strlcpy=no)
+if test "x$found_strlcpy" = xyes; then
+ AC_DEFINE(HAVE_STRLCPY)
+fi
+AM_CONDITIONAL(NO_STRLCPY, [test "x$found_strlcpy" = xno])
+
+# Look for strlcat, compat/strlcat.c used if missing.
+AC_CHECK_FUNC(strlcat, found_strlcat=yes, found_strlcat=no)
+if test "x$found_strlcat" = xyes; then
+ AC_DEFINE(HAVE_STRLCAT)
+fi
+AM_CONDITIONAL(NO_STRLCAT, [test "x$found_strlcat" = xno])
+
+# Look for asprintf, compat/asprintf.c used if missing.
+AC_CHECK_FUNC(asprintf, found_asprintf=yes, found_asprintf=no)
+if test "x$found_asprintf" = xyes; then
+ AC_DEFINE(HAVE_ASPRINTF)
+fi
+AM_CONDITIONAL(NO_ASPRINTF, [test "x$found_asprintf" = xno])
+
+# Look for fgetln, compat/fgetln.c used if missing.
+AC_CHECK_FUNC(fgetln, found_fgetln=yes, found_fgetln=no)
+if test "x$found_fgetln" = xyes; then
+ AC_DEFINE(HAVE_FGETLN)
+fi
+AM_CONDITIONAL(NO_FGETLN, [test "x$found_fgetln" = xno])
+
+# Look for strcasestr, compat/strcasestr.c used if missing.
+AC_CHECK_FUNC(strcasestr, found_strcasestr=yes, found_strcasestr=no)
+if test "x$found_strcasestr" = xyes; then
+ AC_DEFINE(HAVE_STRCASESTR)
+fi
+AM_CONDITIONAL(NO_STRCASESTR, [test "x$found_strcasestr" = xno])
+
+# Look for strsep, compat/strsep.c used if missing.
+AC_CHECK_FUNC(strsep, found_strsep=yes, found_strsep=no)
+if test "x$found_strsep" = xyes; then
+ AC_DEFINE(HAVE_STRSEP)
+fi
+AM_CONDITIONAL(NO_STRSEP, [test "x$found_strsep" = xno])
+
+# Look for strtonum, compat/strtonum.c used if missing.
+AC_CHECK_FUNC(strtonum, found_strtonum=yes, found_strtonum=no)
+if test "x$found_strtonum" = xyes; then
+ AC_DEFINE(HAVE_STRTONUM)
+fi
+AM_CONDITIONAL(NO_STRTONUM, [test "x$found_strtonum" = xno])
+
+# Look for strnvis, compat/{vis,unvis}.c used if missing.
+AC_CHECK_FUNC(strnvis, found_strnvis=yes, found_strnvis=no)
+if test "x$found_strnvis" = xyes; then
+ AC_DEFINE(HAVE_VIS)
+fi
+AM_CONDITIONAL(NO_VIS, [test "x$found_strnvis" = xno])
+
+# Look for getopt. glibc's getopt does not enforce argument order and the ways
+# of making it do so are stupid, so just use our own instead.
+AC_CHECK_FUNC(getopt, found_getopt=yes, found_getopt=no)
+if test "x$found_getopt" != xno; then
+ AC_CHECK_DECLS(
+ [optarg, optind, optreset],
+ ,
+ found_getopt=no,
+ [
+ #include <unistd.h>
+ ]
+ )
+ if test "x$found_getopt" != xno; then
+ AC_MSG_CHECKING(if system getopt should be avoided)
+ if test "x$found_glibc" = xyes; then
+ found_getopt=no
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ AC_DEFINE(HAVE_GETOPT)
+ fi
+ fi
+fi
+AM_CONDITIONAL(NO_GETOPT, [test "x$found_getopt" = xno])
+
+# Check for some functions that are replaced or omitted.
+AC_CHECK_FUNCS(
+ [ \
+ bzero \
+ dirfd \
+ setproctitle \
+ sysconf \
+ ]
+)
+
+# Check for BSD-style integer types.
+AC_MSG_CHECKING(for BSD-style unsigned types)
+AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [
+ #include <sys/types.h>
+ #ifdef HAVE_STDINT_H
+ #include <stdint.h>
+ #else
+ #include <inttypes.h>
+ #endif
+ int main(void)
+ { u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; }
+ ])],
+ [AC_DEFINE(HAVE_BSD_TYPES) AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no)
+)
+
+# Look for a suitable queue.h.
+AC_CHECK_DECL(
+ TAILQ_PREV,
+ found_queue_h=yes,
+ found_queue_h=no,
+ [#include <sys/queue.h>]
+)
+AC_CHECK_DECL(
+ TAILQ_REPLACE,
+ ,
+ found_queue_h=no,
+ [#include <sys/queue.h>]
+)
+if test "x$found_queue_h" = xyes; then
+ AC_DEFINE(HAVE_QUEUE_H)
+fi
+
+# Look for __progname.
+AC_MSG_CHECKING(for __progname)
+AC_LINK_IFELSE([AC_LANG_SOURCE(
+ [
+ #include <stdio.h>
+ #include <stdlib.h>
+ extern char *__progname;
+ int main(void) {
+ const char *cp = __progname;
+ printf("%s\n", cp);
+ exit(0);
+ }
+ ])],
+ [AC_DEFINE(HAVE___PROGNAME) AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no)
+)
+
+# Look for fcntl(F_CLOSEM).
+AC_CHECK_DECL(
+ F_CLOSEM,
+ AC_DEFINE(HAVE_FCNTL_CLOSEM),
+ ,
+ [#include <fcntl.h>]
+)
+
+# Look for /proc/$$.
+AC_MSG_CHECKING(for /proc/\$\$)
+if test -d /proc/$$; then
+ AC_DEFINE(HAVE_PROC_PID)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+# Figure out the platform for osdep-*.c and forkpty-*.c.
+AC_MSG_CHECKING(platform)
+case "$host_os" in
+ *aix*)
+ AC_MSG_RESULT(aix)
+ PLATFORM=aix
+ ;;
+ *darwin*)
+ AC_MSG_RESULT(darwin)
+ AC_DEFINE(BROKEN_CMSG_FIRSTHDR)
+ PLATFORM=darwin
+ ;;
+ *dragonfly*)
+ AC_MSG_RESULT(dragonfly)
+ PLATFORM=dragonfly
+ ;;
+ *linux*)
+ AC_MSG_RESULT(linux)
+ PLATFORM=linux
+ ;;
+ *freebsd*)
+ AC_MSG_RESULT(freebsd)
+ PLATFORM=freebsd
+ ;;
+ *netbsd*)
+ AC_MSG_RESULT(netbsd)
+ PLATFORM=netbsd
+ ;;
+ *openbsd*)
+ AC_MSG_RESULT(openbsd)
+ PLATFORM=openbsd
+ ;;
+ *sunos*)
+ AC_MSG_RESULT(sunos)
+ PLATFORM=sunos
+ ;;
+ *solaris*)
+ AC_MSG_RESULT(sunos)
+ PLATFORM=sunos
+ ;;
+ *hpux*)
+ AC_MSG_RESULT(hpux)
+ PLATFORM=hpux
+ ;;
+ *)
+ AC_MSG_RESULT(unknown)
+ PLATFORM=unknown
+ ;;
+esac
+AC_SUBST(PLATFORM)
+AM_CONDITIONAL(IS_AIX, test "x$PLATFORM" = xaix)
+AM_CONDITIONAL(IS_DARWIN, test "x$PLATFORM" = xdarwin)
+AM_CONDITIONAL(IS_DRAGONFLY, test "x$PLATFORM" = xdragonfly)
+AM_CONDITIONAL(IS_LINUX, test "x$PLATFORM" = xlinux)
+AM_CONDITIONAL(IS_FREEBSD, test "x$PLATFORM" = xfreebsd)
+AM_CONDITIONAL(IS_NETBSD, test "x$PLATFORM" = xnetbsd)
+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_UNKNOWN, test "x$PLATFORM" = xunknown)
+
+# autoconf should create a Makefile. A shock!
+AC_OUTPUT(Makefile)
diff --git a/control.c b/control.c
index 8986f5c6..ba243fd3 100644
--- a/control.c
+++ b/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/environ.c b/environ.c
index 2374d764..3c0a5cb2 100644
--- a/environ.c
+++ b/environ.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/examples/bash_completion_tmux.sh b/examples/bash_completion_tmux.sh
new file mode 100644
index 00000000..74728b91
--- /dev/null
+++ b/examples/bash_completion_tmux.sh
@@ -0,0 +1,105 @@
+# START tmux completion
+# This file is in the public domain
+# See: http://www.debian-administration.org/articles/317 for how to write more.
+# Usage: Put "source bash_completion_tmux.sh" into your .bashrc
+_tmux()
+{
+ local cur prev opts
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+ opts=" \
+ attach-session \
+ bind-key \
+ break-pane \
+ capture-pane \
+ choose-client \
+ choose-session \
+ choose-window \
+ clear-history \
+ clock-mode \
+ command-prompt \
+ confirm-before \
+ copy-buffer \
+ copy-mode \
+ delete-buffer \
+ detach-client \
+ display-message \
+ display-panes \
+ down-pane \
+ find-window \
+ has-session \
+ if-shell \
+ join-pane \
+ kill-pane \
+ kill-server \
+ kill-session \
+ kill-window \
+ last-window \
+ link-window \
+ list-buffers \
+ list-clients \
+ list-commands \
+ list-keys \
+ list-panes \
+ list-sessions \
+ list-windows \
+ load-buffer \
+ lock-client \
+ lock-server \
+ lock-session \
+ move-window \
+ new-session \
+ new-window \
+ next-layout \
+ next-window \
+ paste-buffer \
+ pipe-pane \
+ previous-layout \
+ previous-window \
+ refresh-client \
+ rename-session \
+ rename-window \
+ resize-pane \
+ respawn-window \
+ rotate-window \
+ run-shell \
+ save-buffer \
+ select-layout \
+ select-pane \
+ select-prompt \
+ select-window \
+ send-keys \
+ send-prefix \
+ server-info \
+ set-buffer \
+ set-environment \
+ set-option \
+ set-window-option \
+ show-buffer \
+ show-environment \
+ show-messages \
+ show-options \
+ show-window-options \
+ source-file \
+ split-window \
+ start-server \
+ suspend-client \
+ swap-pane \
+ swap-window \
+ switch-client \
+ unbind-key \
+ unlink-window \
+ up-pane"
+
+ COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
+ return 0
+
+}
+complete -F _tmux tmux
+
+# END tmux completion
+
+
+
diff --git a/examples/h-boetes.conf b/examples/h-boetes.conf
new file mode 100644
index 00000000..2aa86dc5
--- /dev/null
+++ b/examples/h-boetes.conf
@@ -0,0 +1,42 @@
+# $Id: h-boetes.conf,v 1.2 2009-10-25 21:45:26 nicm Exp $
+#
+# From Han Boetes.
+
+set -g default-command zsh
+set -g status-right "#(uptime|awk '{print $11}') #(date)"
+
+# Statusbar properties.
+set -g display-time 3000
+set -g status-bg black
+set -g status-fg cyan
+set-window-option -g window-status-current-attr bright,reverse
+set-window-option -g window-status-current-bg cyan
+set-window-option -g window-status-current-fg black
+
+# Use c-t instead of c-b as the prefix
+unbind C-b
+set -g prefix C-t
+bind C-t send-prefix
+bind t send-prefix
+
+# Bind function keys.
+bind -n F1 select-window -t 1
+bind -n F2 select-window -t 2
+bind -n F3 select-window -t 3
+bind -n F4 select-window -t 4
+bind -n F5 select-window -t 5
+bind -n F6 select-window -t 6
+bind -n F7 select-window -t 7
+bind -n F8 select-window -t 8
+
+# All new windows started at startup.
+new emacs
+neww irssi
+neww mutt
+neww
+neww
+neww
+neww
+neww
+
+select-window -t 1
diff --git a/examples/n-marriott.conf b/examples/n-marriott.conf
new file mode 100644
index 00000000..6a047ec9
--- /dev/null
+++ b/examples/n-marriott.conf
@@ -0,0 +1,110 @@
+# $Id: n-marriott.conf,v 1.11 2009-11-24 19:03:59 nicm Exp $
+#
+# By Nicholas Marriott. Public domain.
+
+# Default global options.
+set -g status-bg green
+set -g status-right "%H:%M" # %d-%b-%y
+set -g bell-action none
+set -g lock-after-time 1800
+
+# Default global window options.
+setw -g remain-on-exit on
+setw -g window-status-current-attr "underscore"
+#setw -g xterm-keys on
+
+# Prefix key.
+set -g prefix C-a
+unbind C-b
+bind C-a send-prefix
+
+# Keys to switch session.
+bind Q switchc -t0
+bind W switchc -t1
+bind E switchc -t2
+
+# Other key bindings.
+bind F1 selectw -t:10
+bind F2 selectw -t:11
+bind F3 selectw -t:12
+bind F4 selectw -t:13
+bind F5 selectw -t:14
+bind F6 selectw -t:15
+bind F7 selectw -t:16
+bind F8 selectw -t:17
+bind F9 selectw -t:18
+bind F10 selectw -t:19
+bind F11 selectw -t:20
+bind F12 selectw -t:21
+
+bind m setw monitor-activity
+
+bind y setw force-width 81
+bind u setw force-width 0
+
+bind -n F1 run-shell 'mpc toggle >/dev/null 2>&1'
+bind -n F2 run-shell 'mpc'
+bind -n F3 run-shell 'mpc prev >/dev/null 2>&1'
+bind -n F4 run-shell 'mpc next >/dev/null 2>&1'
+bind -n F5 run-shell 'mpc volume -5 >/dev/null 2>&1'
+bind -n F6 run-shell 'mpc volume +5 >/dev/null 2>&1'
+
+# Hide and show window name from status line
+bind '-' setw window-status-format '#I'\; setw window-status-current-format '#I'
+bind '+' setw window-status-format '#I:#W#F'\; setw window-status-current-format '#I:#W#F'
+
+# First session.
+new -d -s0 -nirssi 'exec ssh -t natalya exec sh ~/bin/tmux-start'
+setw -t0:0 monitor-activity on
+setw -t0:0 aggressive-resize on
+set -t0 status-bg green
+neww -d -ntodo 'exec emacs ~/TODO'
+setw -t0:1 aggressive-resize on
+neww -d -ntodo2 'exec emacs ~/TODO2'
+setw -t0:2 aggressive-resize on
+neww -d -nncmpc 'exec ncmpc -f ~/.ncmpc.conf'
+setw -t0:3 aggressive-resize on
+neww -d -nmutt 'exec mutt'
+setw -t0:4 aggressive-resize on
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+
+# Second session.
+new -d -s1
+set -t1 status-bg cyan
+linkw -dk -t0 -s0:0
+linkw -dk -t1 -s0:1
+linkw -dk -t2 -s0:2
+linkw -dk -t3 -s0:3
+linkw -dk -t4 -s0:4
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+
+# Third session.
+new -d -s2
+set -t2 status-bg yellow
+linkw -dk -t0 -s0:0
+linkw -dk -t1 -s0:1
+linkw -dk -t2 -s0:2
+linkw -dk -t3 -s0:3
+linkw -dk -t4 -s0:4
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
+neww -d
diff --git a/examples/screen-keys.conf b/examples/screen-keys.conf
new file mode 100644
index 00000000..ce149290
--- /dev/null
+++ b/examples/screen-keys.conf
@@ -0,0 +1,102 @@
+# $Id: screen-keys.conf,v 1.7 2010-07-31 11:39:13 nicm Exp $
+#
+# By Nicholas Marriott. Public domain.
+#
+# This configuration file binds many of the common GNU screen key bindings to
+# appropriate tmux key bindings. Note that for some key bindings there is no
+# tmux analogue and also that this set omits binding some commands available in
+# tmux but not in screen.
+#
+# Note this is only a selection of key bindings and they are in addition to the
+# normal tmux key bindings. This is intended as an example not as to be used
+# as-is.
+
+# Set the prefix to ^A.
+unbind C-b
+set -g prefix ^A
+bind a send-prefix
+
+# Bind appropriate commands similar to screen.
+# lockscreen ^X x
+unbind ^X
+bind ^X lock-server
+unbind x
+bind x lock-server
+
+# screen ^C c
+unbind ^C
+bind ^C new-window
+unbind c
+bind c new-window
+
+# detach ^D d
+unbind ^D
+bind ^D detach
+
+# displays *
+unbind *
+bind * list-clients
+
+# next ^@ ^N sp n
+unbind ^@
+bind ^@ next-window
+unbind ^N
+bind ^N next-window
+unbind " "
+bind " " next-window
+unbind n
+bind n next-window
+
+# title A
+unbind A
+bind A command-prompt "rename-window %%"
+
+# other ^A
+unbind ^A
+bind ^A last-window
+
+# prev ^H ^P p ^?
+unbind ^H
+bind ^H previous-window
+unbind ^P
+bind ^P previous-window
+unbind p
+bind p previous-window
+unbind BSpace
+bind BSpace previous-window
+
+# windows ^W w
+unbind ^W
+bind ^W list-windows
+unbind w
+bind w list-windows
+
+# quit \
+unbind '\'
+bind '\' confirm-before "kill-server"
+
+# kill K k
+unbind K
+bind K confirm-before "kill-window"
+unbind k
+bind k confirm-before "kill-window"
+
+# redisplay ^L l
+unbind ^L
+bind ^L refresh-client
+unbind l
+bind l refresh-client
+
+# split -v |
+unbind |
+bind | split-window
+
+# :kB: focus up
+unbind Tab
+bind Tab select-pane -t:.+
+unbind BTab
+bind BTab select-pane -t:.-
+
+# " windowlist -b
+unbind '"'
+bind '"' choose-window
diff --git a/examples/t-williams.conf b/examples/t-williams.conf
new file mode 100644
index 00000000..0a2cc3f5
--- /dev/null
+++ b/examples/t-williams.conf
@@ -0,0 +1,104 @@
+# $Id: t-williams.conf,v 1.1 2009-11-02 18:59:28 nicm Exp $
+#
+# ~/.tmux.conf - tmux terminal multiplexer config
+# Thayer Williams (http://cinderwick.ca)
+# "Feel free to do whatever you like with it."
+
+# I typically start tmux from ~/.xinitrc with the following:
+#
+# urxvt -e bash -c "tmux attach -d -t mysession" &
+#
+# and recall it any time thereafter with xbindkeys (Mod4+s):
+#
+# "urxvt -e bash -c 'tmux attach -d -t mysession'"
+# m:0x50 + c:39
+
+
+# set prefix key to ctrl+a until I have time to adapt
+unbind C-b
+set -g prefix C-a
+
+# send the prefix to client inside window (ala nested sessions)
+bind-key a send-prefix
+
+# toggle last window like screen
+bind-key C-a last-window
+
+# confirm before killing a window or the server
+bind-key k confirm kill-window
+bind-key K confirm kill-server
+
+# toggle statusbar
+bind-key b set-option status
+
+# ctrl+left/right cycles thru windows
+bind-key -n C-right next
+bind-key -n C-left prev
+
+# open a man page in new window
+bind / command-prompt "split-window 'exec man %%'"
+
+# quick view of processes
+bind '~' split-window "exec htop"
+
+# scrollback buffer n lines
+set -g history-limit 5000
+
+# listen for activity on all windows
+set -g bell-action any
+
+# on-screen time for display-panes in ms
+set -g display-panes-time 2000
+
+# start window indexing at one instead of zero
+set -g base-index 1
+
+# enable wm window titles
+set -g set-titles on
+
+# wm window title string (uses statusbar variables)
+set -g set-titles-string "tmux.#I.#W"
+
+# session initialization
+new -s mysession mutt
+neww -t 2
+neww -d -t 3
+neww -d -t 5 mocp
+neww -d -t 6 rtorrent
+selectw -t 1
+
+# statusbar --------------------------------------------------------------
+
+set -g display-time 2000
+
+# default statusbar colors
+set -g status-fg white
+set -g status-bg default
+set -g status-attr default
+
+# default window title colors
+set-window-option -g window-status-fg cyan
+set-window-option -g window-status-bg default
+set-window-option -g window-status-attr dim
+
+# active window title colors
+set-window-option -g window-status-current-fg white
+set-window-option -g window-status-current-bg default
+set-window-option -g window-status-current-attr bright
+
+# command/message line colors
+set -g message-fg white
+set -g message-bg black
+set -g message-attr bright
+
+# center align the window list
+set -g status-justify centre
+
+# show some useful stats but only when tmux is started
+# outside of Xorg, otherwise dwm statusbar shows these already
+set -g status-right ""
+set -g status-left ""
+if '[ -z "$DISPLAY" ]' 'set -g status-left "[#[fg=green] #H #[default]]"'
+if '[ -z "$DISPLAY" ]' 'set -g status-right "[ #[fg=magenta]#(cat /proc/loadavg | cut -d \" \" -f 1,2,3)#[default] ][ #[fg=cyan,bright]%a %Y-%m-%d %H:%M #[default]]"'
+if '[ -z "$DISPLAY" ]' 'set -g status-right-length 50'
+
diff --git a/examples/tmux.vim b/examples/tmux.vim
new file mode 100644
index 00000000..076115c1
--- /dev/null
+++ b/examples/tmux.vim
@@ -0,0 +1,126 @@
+" Vim syntax file
+" Language: tmux(1) configuration file
+" Maintainer: Tiago Cunha <tcunha@users.sourceforge.net>
+" Last Change: $Date: 2010-07-27 18:29:07 $
+" License: This file is placed in the public domain.
+"
+" To install this file:
+"
+" - Drop the file in the syntax directory into runtimepath (such as
+" ~/.vim/syntax/tmux.vim).
+" - Make the filetype recognisable by adding the following to filetype.vim
+" (~/.vim/filetype.vim):
+"
+" augroup filetypedetect
+" au BufNewFile,BufRead .tmux.conf*,tmux.conf* setf tmux
+" augroup END
+"
+" - Switch on syntax highlighting by adding "syntax enable" to .vimrc.
+"
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+setlocal iskeyword+=-
+syntax case match
+
+syn keyword tmuxAction any current none
+syn keyword tmuxBoolean off on
+
+syn keyword tmuxCmds
+ \ attach[-session] detach[-client] has[-session] kill-server
+ \ kill-session lsc list-clients lscm list-commands ls list-sessions
+ \ lockc lock-client locks lock-session new[-session] refresh[-client]
+ \ rename[-session] showmsgs show-messages source[-file] start[-server]
+ \ suspendc suspend-client switchc switch-client
+ \ copy-mode
+ \ breakp break-pane capturep capture-pane choose-client choose-session
+ \ choose-tree choose-window displayp display-panes findw find-window
+ \ joinp join-pane killp kill-pane killw kill-window lastp last-pane
+ \ last[-window] linkw link-window lsp list-panes lsw list-windows movep
+ \ move-pane movew move-window neww new-window nextl next-layout
+ \ next[-window] pipep pipe-pane prevl previous-layout prev[ious-window]
+ \ renamew rename-window resizep resize-pane respawnp respawn-pane
+ \ respawnw respawn-window rotatew rotate-window selectl select-layout
+ \ selectp select-pane selectw select-window splitw split-window swapp
+ \ swap-pane swapw swap-window unlinkw unlink-window
+ \ bind[-key] lsk list-keys send[-keys] send-prefix unbind[-key]
+ \ set[-option] setw set-window-option show[-options] showw
+ \ show-window-options
+ \ setenv set-environment showenv show-environment
+ \ command-prompt confirm[-before] display[-message]
+ \ choose-buffer clearhist clear-history deleteb delete-buffer lsb
+ \ list-buffers loadb load-buffer pasteb paste-buffer saveb save-buffer
+ \ setb set-buffer showb show-buffer
+ \ clock-mode if[-shell] lock[-server] run[-shell] server-info info
+ \ choose-list
+
+syn keyword tmuxOptsSet
+ \ buffer-limit escape-time exit-unattached exit-unattached quiet
+ \ set-clipboard
+ \ base-index bell-action bell-on-alert default-command default-path
+ \ default-shell default-terminal destroy-unattached detach-on-destroy
+ \ display-panes-active-colour display-panes-colour display-panes-time
+ \ display-time history-limit
+ \ lock-after-time lock-command lock-server
+ \ message-command-attr message-attr message-command-bg message-bg
+ \ message-command-fg message-fg message-limit
+ \ mouse-resize-pane mouse-select-pane mouse-select-window mouse-utf8
+ \ pane-active-border-bg pane-border-bg pane-active-border-fg
+ \ pane-border-fg prefix prefix2
+ \ renumber-windows repeat-time set-remain-on-exit set-titles
+ \ set-titles-string status status-attr status-bg status-fg
+ \ status-interval status-justify status-keys status-left
+ \ status-left-attr status-left-bg status-left-fg status-left-length
+ \ status-position status-right status-right-attr status-right-bg
+ \ status-right-fg status-right-length status-utf8 terminal-overrides
+ \ update-environment visual-activity visual-bell visual-content
+ \ visual-silence word-separators
+
+syn keyword tmuxOptsSetw
+ \ aggressive-resize alternate-screen automatic-rename
+ \ c0-change-interval c0-change-trigger clock-mode-colour
+ \ clock-mode-style force-height force-width layout-history-limit
+ \ main-pane-height main-pane-width mode-attr mode-bg mode-fg move-keys
+ \ mode-mouse monitor-activity monitor-content monitor-silence
+ \ other-pane-height other-pane-width pane-base-index remain-on-exit
+ \ synchronize-panes utf8 window-status-bell-attr window-status-bell-bg
+ \ window-status-bell-fg window-status-content-attr
+ \ window-status-content-bg window-status-content-fg
+ \ window-status-activity-attr window-status-activity-bg
+ \ window-status-activity-fg window-status-attr
+ \ window-status-current-attr window-status-attr window-status-current-bg
+ \ window-status-bg window-status-current-fg window-status-fg
+ \ window-status-current-format window-status-format
+ \ window-status-separator xterm-keys wrap-search
+
+syn keyword tmuxTodo FIXME NOTE TODO XXX contained
+
+syn match tmuxKey /\(C-\|M-\|\^\)\+\S\+/ display
+syn match tmuxNumber /\d\+/ display
+syn match tmuxOptions /\s-\a\+/ display
+syn match tmuxVariable /\w\+=/ display
+syn match tmuxVariableExpansion /\${\=\w\+}\=/ display
+
+syn region tmuxComment start=/#/ end=/$/ contains=tmuxTodo display oneline
+syn region tmuxString start=/"/ end=/"/ display oneline
+syn region tmuxString start=/'/ end=/'/ display oneline
+
+hi def link tmuxAction Boolean
+hi def link tmuxBoolean Boolean
+hi def link tmuxCmds Keyword
+hi def link tmuxComment Comment
+hi def link tmuxKey Special
+hi def link tmuxNumber Number
+hi def link tmuxOptions Identifier
+hi def link tmuxOptsSet Function
+hi def link tmuxOptsSetw Function
+hi def link tmuxString String
+hi def link tmuxTodo Todo
+hi def link tmuxVariable Constant
+hi def link tmuxVariableExpansion Constant
+
+let b:current_syntax = "tmux"
diff --git a/examples/tmux_backup.sh b/examples/tmux_backup.sh
new file mode 100644
index 00000000..bc0bf370
--- /dev/null
+++ b/examples/tmux_backup.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+#
+# By Victor Orlikowski. Public domain.
+#
+# This script maintains snapshots of each pane's
+# history buffer, for each tmux session you are running.
+#
+# It is intended to be run by cron, on whatever interval works
+# for you.
+
+# Maximum number of snapshots to keep.
+max_backups=12
+# Names of sessions you may wish to exclude from snapshotting,
+# space separated.
+ignore_sessions=""
+# The directory into which you want your snapshots placed.
+# The default is probably "good enough."
+backup_dir=~/.tmux_backup/snapshot
+
+########################################################################
+
+# Rotate previous backups.
+i=${max_backups}
+while [[ ${i} != 0 ]] ; do
+if [ -d ${backup_dir}.${i} ] ; then
+ if [[ ${i} = ${max_backups} ]] ; then
+ rm -r ${backup_dir}.${i}
+ else
+ mv ${backup_dir}.${i} ${backup_dir}.$((${i}+1))
+ fi
+fi
+i=$((${i}-1))
+done
+
+if [ -d ${backup_dir} ] ; then
+ mv ${backup_dir} ${backup_dir}.1
+fi
+
+## Dump hardcopy from all windows in all available tmux sessions.
+unset TMUX
+for session in $(tmux list-sessions | cut -d' ' -f1 | sed -e 's/:$//') ; do
+ for ignore_session in ${ignore_sessions} ; do
+ if [ ${session} = ${ignore_session} ] ; then
+ continue 2
+ fi
+ done
+
+ # Session name can contain the colon character (":").
+ # This can screw up addressing of windows within tmux, since
+ # target windows are specified as target-session:target-window.
+ #
+ # We use uuidgen to create a "safe" temporary session name,
+ # which we then use to create a "detached" session that "links"
+ # to the "real" session that we want to back up.
+ tmpsession=$(uuidgen)
+ tmux new-session -d -s "$tmpsession" -t "$session"
+ HISTSIZE=$(tmux show-options -g -t "$tmpsession" | grep "history-limit" | awk '{print $2}')
+ for win in $(tmux list-windows -t "$tmpsession" | grep -v "^\s" | cut -d' ' -f1 | sed -e 's/:$//'); do
+ session_dir=$(echo "$session" | sed -e 's/ /_/g' | sed -e 's%/%|%g')
+ win_spec="$tmpsession":"$win"
+
+ if [ ! -d ${backup_dir}/${session_dir}/${win} ] ; then
+ mkdir -p ${backup_dir}/${session_dir}/${win}
+ fi
+
+ for pane in $(tmux list-panes -t "$win_spec" | cut -d' ' -f1 | sed -e 's/:$//'); do
+ pane_path=${backup_dir}/${session_dir}/${win}/${pane}
+ pane_spec="$win_spec"."$pane"
+
+ tmux capture-pane -t "$pane_spec" -S -${HISTSIZE}
+ tmux save-buffer ${pane_path}
+
+ if [ ! -s ${pane_path} ] ; then
+ sleep 1
+ rm ${pane_path}
+ fi
+ done
+ done
+ tmux kill-session -t "$tmpsession"
+
+done
diff --git a/examples/vim-keys.conf b/examples/vim-keys.conf
new file mode 100644
index 00000000..d587d0bf
--- /dev/null
+++ b/examples/vim-keys.conf
@@ -0,0 +1,36 @@
+# $Id: vim-keys.conf,v 1.2 2010-09-18 09:36:15 nicm Exp $
+#
+# vim-keys.conf, v1.2 2010/09/12
+#
+# By Daniel Thau. Public domain.
+#
+# This configuration file binds many vi- and vim-like bindings to the
+# appropriate tmux key bindings. Note that for many key bindings there is no
+# tmux analogue. This is intended for tmux 1.3, which handles pane selection
+# differently from the previous versions
+
+# split windows like vim
+# vim's definition of a horizontal/vertical split is reversed from tmux's
+bind s split-window -v
+bind v split-window -h
+
+# move around panes with hjkl, as one would in vim after pressing ctrl-w
+bind h select-pane -L
+bind j select-pane -D
+bind k select-pane -U
+bind l select-pane -R
+
+# resize panes like vim
+# feel free to change the "1" to however many lines you want to resize by, only
+# one at a time can be slow
+bind < resize-pane -L 1
+bind > resize-pane -R 1
+bind - resize-pane -D 1
+bind + resize-pane -U 1
+
+# bind : to command-prompt like vim
+# this is the default in tmux already
+bind : command-prompt
+
+# vi-style controls for copy mode
+setw -g mode-keys vi
diff --git a/format.c b/format.c
index b357876e..fa2dd0b2 100644
--- a/format.c
+++ b/format.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -432,9 +432,9 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_start_command", "%s", wp->cmd);
if (wp->cwd != NULL)
format_add(ft, "pane_start_path", "%s", wp->cwd);
- if ((cwd = get_proc_cwd(wp->fd)) != NULL)
+ if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
format_add(ft, "pane_current_path", "%s", cwd);
- if ((cmd = get_proc_name(wp->fd, wp->tty)) != NULL) {
+ if ((cmd = osdep_get_name(wp->fd, wp->tty)) != NULL) {
format_add(ft, "pane_current_command", "%s", cmd);
free(cmd);
}
diff --git a/grid-view.c b/grid-view.c
index 4fe38fed..7ef443a3 100644
--- a/grid-view.c
+++ b/grid-view.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/grid.c b/grid.c
index 529ce154..2955e8ba 100644
--- a/grid.c
+++ b/grid.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/input-keys.c b/input-keys.c
index d7e8513d..faa7bd17 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,7 +18,6 @@
#include <sys/types.h>
-#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/input.c b/input.c
index 0dcdee96..4aa02e90 100644
--- a/input.c
+++ b/input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/job.c b/job.c
index b76b3345..6a7286ae 100644
--- a/job.c
+++ b/job.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,7 +20,6 @@
#include <sys/socket.h>
#include <fcntl.h>
-#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
diff --git a/key-bindings.c b/key-bindings.c
index 625ffddf..86048ea6 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/key-string.c b/key-string.c
index 7aba190b..797eedd5 100644
--- a/key-string.c
+++ b/key-string.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/layout-custom.c b/layout-custom.c
index c9cf49c2..e32d9d9d 100644
--- a/layout-custom.c
+++ b/layout-custom.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/layout-set.c b/layout-set.c
index 98ed9736..646528ba 100644
--- a/layout-set.c
+++ b/layout-set.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/layout.c b/layout.c
index 4dd3756c..b74bd789 100644
--- a/layout.c
+++ b/layout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/log.c b/log.c
index 2f1400cb..dbf9ee15 100644
--- a/log.c
+++ b/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/mode-key.c b/mode-key.c
index 54abcf32..94115ebb 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/names.c b/names.c
index 76dec82c..f536d2fc 100644
--- a/names.c
+++ b/names.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -62,7 +62,7 @@ window_name_callback(unused int fd, unused short events, void *data)
if (w->active->screen != &w->active->base)
name = NULL;
else
- name = get_proc_name(w->active->fd, w->active->tty);
+ name = osdep_get_name(w->active->fd, w->active->tty);
if (name == NULL)
wname = default_window_name(w);
else {
diff --git a/notify.c b/notify.c
index 75a16de9..bd5c7d83 100644
--- a/notify.c
+++ b/notify.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2012 George Nachman <tmux@georgester.com>
@@ -17,7 +17,6 @@
*/
#include <sys/types.h>
-#include <sys/queue.h>
#include <stdlib.h>
diff --git a/options-table.c b/options-table.c
index ae711882..76a61619 100644
--- a/options-table.c
+++ b/options-table.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <string.h>
-#include <paths.h>
#include "tmux.h"
diff --git a/options.c b/options.c
index ec036741..7360906b 100644
--- a/options.c
+++ b/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/osdep-aix.c b/osdep-aix.c
new file mode 100644
index 00000000..8d590816
--- /dev/null
+++ b/osdep-aix.c
@@ -0,0 +1,41 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <event.h>
+
+#include "tmux.h"
+
+char *
+osdep_get_name(unused int fd, unused char *tty)
+{
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(unused int fd)
+{
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/osdep-darwin.c b/osdep-darwin.c
new file mode 100644
index 00000000..23de9d52
--- /dev/null
+++ b/osdep-darwin.c
@@ -0,0 +1,80 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <event.h>
+#include <libproc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+char *osdep_get_name(int, char *);
+char *osdep_get_cwd(int);
+struct event_base *osdep_event_init(void);
+
+#define unused __attribute__ ((unused))
+
+char *
+osdep_get_name(int fd, unused char *tty)
+{
+ struct proc_bsdshortinfo bsdinfo;
+ pid_t pgrp;
+ int ret;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ ret = proc_pidinfo(pgrp, PROC_PIDT_SHORTBSDINFO, 0,
+ &bsdinfo, sizeof bsdinfo);
+ if (ret == sizeof bsdinfo && *bsdinfo.pbsi_comm != '\0')
+ return (strdup(bsdinfo.pbsi_comm));
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ static char wd[PATH_MAX];
+ struct proc_vnodepathinfo pathinfo;
+ pid_t pgrp;
+ int ret;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ ret = proc_pidinfo(pgrp, PROC_PIDVNODEPATHINFO, 0,
+ &pathinfo, sizeof pathinfo);
+ if (ret == sizeof pathinfo) {
+ strlcpy(wd, pathinfo.pvi_cdir.vip_path, sizeof wd);
+ return (wd);
+ }
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ /*
+ * On OS X, kqueue and poll are both completely broken and don't
+ * work on anything except socket file descriptors (yes, really).
+ */
+ setenv("EVENT_NOKQUEUE", "1", 1);
+ setenv("EVENT_NOPOLL", "1", 1);
+ return (event_init());
+}
diff --git a/osdep-dragonfly.c b/osdep-dragonfly.c
new file mode 100644
index 00000000..ad417d98
--- /dev/null
+++ b/osdep-dragonfly.c
@@ -0,0 +1,133 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
+char *osdep_get_name(int, char *);
+char *osdep_get_cwd(int);
+struct event_base *osdep_event_init(void);
+
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+#define is_runnable(p) \
+ ((p)->kp_stat == SACTIVE || (p)->kp_stat == SIDL)
+#define is_stopped(p) \
+ ((p)->kp_stat == SSTOP || (p)->kp_stat == SZOMB)
+
+struct kinfo_proc *
+cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
+{
+ if (is_runnable(p1) && !is_runnable(p2))
+ return (p1);
+ if (!is_runnable(p1) && is_runnable(p2))
+ return (p2);
+
+ if (is_stopped(p1) && !is_stopped(p2))
+ return (p1);
+ if (!is_stopped(p1) && is_stopped(p2))
+ return (p2);
+
+ if (strcmp(p1->kp_comm, p2->kp_comm) < 0)
+ return (p1);
+ if (strcmp(p1->kp_comm, p2->kp_comm) > 0)
+ return (p2);
+
+ if (p1->kp_pid > p2->kp_pid)
+ return (p1);
+ return (p2);
+}
+
+char *
+osdep_get_name(int fd, char *tty)
+{
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 };
+ struct stat sb;
+ size_t len;
+ struct kinfo_proc *buf, *newbuf, *bestp;
+ u_int i;
+ char *name;
+
+ buf = NULL;
+
+ if (stat(tty, &sb) == -1)
+ return (NULL);
+ if ((mib[3] = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+retry:
+ if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
+ return (NULL);
+ len = (len * 5) / 4;
+
+ if ((newbuf = realloc(buf, len)) == NULL)
+ goto error;
+ buf = newbuf;
+
+ if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ goto retry;
+ goto error;
+ }
+
+ bestp = NULL;
+ for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
+ if (buf[i].kp_tdev != sb.st_rdev)
+ continue;
+ if (bestp == NULL)
+ bestp = &buf[i];
+ else
+ bestp = cmp_procs(&buf[i], bestp);
+ }
+
+ name = NULL;
+ if (bestp != NULL)
+ name = strdup(bestp->kp_comm);
+
+ free(buf);
+ return (name);
+
+error:
+ free(buf);
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/osdep-freebsd.c b/osdep-freebsd.c
new file mode 100644
index 00000000..d596eab4
--- /dev/null
+++ b/osdep-freebsd.c
@@ -0,0 +1,170 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libutil.h>
+
+struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
+char *osdep_get_name(int, char *);
+char *osdep_get_cwd(int);
+struct event_base *osdep_event_init(void);
+
+#ifndef nitems
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+#define is_runnable(p) \
+ ((p)->ki_stat == SRUN || (p)->ki_stat == SIDL)
+#define is_stopped(p) \
+ ((p)->ki_stat == SSTOP || (p)->ki_stat == SZOMB)
+
+struct kinfo_proc *
+cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
+{
+ if (is_runnable(p1) && !is_runnable(p2))
+ return (p1);
+ if (!is_runnable(p1) && is_runnable(p2))
+ return (p2);
+
+ if (is_stopped(p1) && !is_stopped(p2))
+ return (p1);
+ if (!is_stopped(p1) && is_stopped(p2))
+ return (p2);
+
+ if (p1->ki_estcpu > p2->ki_estcpu)
+ return (p1);
+ if (p1->ki_estcpu < p2->ki_estcpu)
+ return (p2);
+
+ if (p1->ki_slptime < p2->ki_slptime)
+ return (p1);
+ if (p1->ki_slptime > p2->ki_slptime)
+ return (p2);
+
+ if (strcmp(p1->ki_comm, p2->ki_comm) < 0)
+ return (p1);
+ if (strcmp(p1->ki_comm, p2->ki_comm) > 0)
+ return (p2);
+
+ if (p1->ki_pid > p2->ki_pid)
+ return (p1);
+ return (p2);
+}
+
+char *
+osdep_get_name(int fd, char *tty)
+{
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 };
+ struct stat sb;
+ size_t len;
+ struct kinfo_proc *buf, *newbuf, *bestp;
+ u_int i;
+ char *name;
+
+ buf = NULL;
+
+ if (stat(tty, &sb) == -1)
+ return (NULL);
+ if ((mib[3] = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+retry:
+ if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
+ return (NULL);
+ len = (len * 5) / 4;
+
+ if ((newbuf = realloc(buf, len)) == NULL)
+ goto error;
+ buf = newbuf;
+
+ if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ goto retry;
+ goto error;
+ }
+
+ bestp = NULL;
+ for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
+ if (buf[i].ki_tdev != sb.st_rdev)
+ continue;
+ if (bestp == NULL)
+ bestp = &buf[i];
+ else
+ bestp = cmp_procs(&buf[i], bestp);
+ }
+
+ name = NULL;
+ if (bestp != NULL)
+ name = strdup(bestp->ki_comm);
+
+ free(buf);
+ return (name);
+
+error:
+ free(buf);
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ static char wd[PATH_MAX];
+ struct kinfo_file *info = NULL;
+ pid_t pgrp;
+ int nrecords, i;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ if ((info = kinfo_getfile(pgrp, &nrecords)) == NULL)
+ return (NULL);
+
+ for (i = 0; i < nrecords; i++) {
+ if (info[i].kf_fd == KF_FD_TYPE_CWD) {
+ strlcpy(wd, info[i].kf_path, sizeof wd);
+ free(info);
+ return (wd);
+ }
+ }
+
+ free(info);
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ /*
+ * On some versions of FreeBSD, kqueue doesn't work properly on tty
+ * file descriptors. This is fixed in recent FreeBSD versions.
+ */
+ setenv("EVENT_NOKQUEUE", "1", 1);
+ return (event_init());
+}
diff --git a/osdep-hpux.c b/osdep-hpux.c
new file mode 100644
index 00000000..352e375b
--- /dev/null
+++ b/osdep-hpux.c
@@ -0,0 +1,41 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <event.h>
+
+#include "tmux.h"
+
+char *
+osdep_get_name(unused int fd, unused char *tty)
+{
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(unused int fd)
+{
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/osdep-linux.c b/osdep-linux.c
new file mode 100644
index 00000000..b65acffc
--- /dev/null
+++ b/osdep-linux.c
@@ -0,0 +1,97 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <event.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+char *
+osdep_get_name(int fd, unused char *tty)
+{
+ FILE *f;
+ char *path, *buf;
+ size_t len;
+ int ch;
+ pid_t pgrp;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ xasprintf(&path, "/proc/%lld/cmdline", (long long) pgrp);
+ if ((f = fopen(path, "r")) == NULL) {
+ free(path);
+ return (NULL);
+ }
+ free(path);
+
+ len = 0;
+ buf = NULL;
+ while ((ch = fgetc(f)) != EOF) {
+ if (ch == '\0')
+ break;
+ buf = xrealloc(buf, 1, len + 2);
+ buf[len++] = ch;
+ }
+ if (buf != NULL)
+ buf[len] = '\0';
+
+ fclose(f);
+ return (buf);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ static char target[MAXPATHLEN + 1];
+ char *path;
+ pid_t pgrp;
+ ssize_t n;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ xasprintf(&path, "/proc/%lld/cwd", (long long) pgrp);
+ n = readlink(path, target, MAXPATHLEN);
+ free(path);
+ if (n > 0) {
+ target[n] = '\0';
+ return (target);
+ }
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ /*
+ * On Linux, epoll doesn't work on /dev/null (yes, really).
+ *
+ * This has been commented because libevent versions up until the very
+ * latest (1.4 git or 2.0.10) do not handle signals properly when using
+ * poll or select, causing hangs.
+ *
+ */
+ /* setenv("EVENT_NOEPOLL", "1", 1); */
+ return (event_init());
+}
diff --git a/osdep-netbsd.c b/osdep-netbsd.c
new file mode 100644
index 00000000..f16d0dc8
--- /dev/null
+++ b/osdep-netbsd.c
@@ -0,0 +1,137 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <event.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define is_runnable(p) \
+ ((p)->p_stat == LSRUN || (p)->p_stat == SIDL)
+#define is_stopped(p) \
+ ((p)->p_stat == SSTOP || (p)->p_stat == SZOMB)
+
+struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *);
+char *osdep_get_name(int, char *);
+char *osdep_get_cwd(int);
+struct event_base *osdep_event_init(void);
+
+struct kinfo_proc2 *
+cmp_procs(struct kinfo_proc2 *p1, struct kinfo_proc2 *p2)
+{
+ if (is_runnable(p1) && !is_runnable(p2))
+ return (p1);
+ if (!is_runnable(p1) && is_runnable(p2))
+ return (p2);
+
+ if (is_stopped(p1) && !is_stopped(p2))
+ return (p1);
+ if (!is_stopped(p1) && is_stopped(p2))
+ return (p2);
+
+ if (p1->p_estcpu > p2->p_estcpu)
+ return (p1);
+ if (p1->p_estcpu < p2->p_estcpu)
+ return (p2);
+
+ if (p1->p_slptime < p2->p_slptime)
+ return (p1);
+ if (p1->p_slptime > p2->p_slptime)
+ return (p2);
+
+ if (p1->p_pid > p2->p_pid)
+ return (p1);
+ return (p2);
+}
+
+char *
+osdep_get_name(int fd, __unused char *tty)
+{
+ int mib[6];
+ struct stat sb;
+ size_t len, i;
+ struct kinfo_proc2 *buf, *newbuf, *bestp;
+ char *name;
+
+ if (stat(tty, &sb) == -1)
+ return (NULL);
+ if ((mib[3] = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ buf = NULL;
+ len = sizeof(bestp);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC2;
+ mib[2] = KERN_PROC_PGRP;
+ mib[4] = sizeof (*buf);
+ mib[5] = 0;
+
+retry:
+ if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1)
+ return (NULL);
+
+ if ((newbuf = realloc(buf, len * sizeof (*buf))) == NULL)
+ goto error;
+ buf = newbuf;
+
+ mib[5] = len / sizeof(*buf);
+ if (sysctl(mib, __arraycount(mib), buf, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ goto retry; /* possible infinite loop? */
+ goto error;
+ }
+
+ bestp = NULL;
+ for (i = 0; i < len / sizeof (*buf); i++) {
+ if (buf[i].p_tdev != sb.st_rdev)
+ continue;
+ if (bestp == NULL)
+ bestp = &buf[i];
+ else
+ bestp = cmp_procs(&buf[i], bestp);
+ }
+
+ name = NULL;
+ if (bestp != NULL)
+ name = strdup(bestp->p_comm);
+
+ free(buf);
+ return (name);
+
+error:
+ free(buf);
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/procname.c b/osdep-openbsd.c
index 1518c94b..7be38a91 100644
--- a/procname.c
+++ b/osdep-openbsd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,6 +22,7 @@
#include <sys/stat.h>
#include <errno.h>
+#include <event.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -36,8 +37,9 @@
((p)->p_stat == SSTOP || (p)->p_stat == SZOMB || (p)->p_stat == SDEAD)
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
-char *get_proc_name(int, char *);
-char *get_proc_cwd(int);
+char *osdep_get_name(int, char *);
+char *osdep_get_cwd(int);
+struct event_base *osdep_event_init(void);
struct kinfo_proc *
cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
@@ -78,7 +80,7 @@ cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
}
char *
-get_proc_name(int fd, char *tty)
+osdep_get_name(int fd, char *tty)
{
int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0,
sizeof(struct kinfo_proc), 0 };
@@ -134,7 +136,7 @@ error:
}
char*
-get_proc_cwd(int fd)
+osdep_get_cwd(int fd)
{
int name[] = { CTL_KERN, KERN_PROC_CWD, 0 };
static char path[MAXPATHLEN];
@@ -146,3 +148,9 @@ get_proc_cwd(int fd)
return (NULL);
return (path);
}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/osdep-sunos.c b/osdep-sunos.c
new file mode 100644
index 00000000..fd644f5d
--- /dev/null
+++ b/osdep-sunos.c
@@ -0,0 +1,92 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Todd Carson <toc@daybefore.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <event.h>
+#include <fcntl.h>
+#include <procfs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+char *
+osdep_get_name(int fd, char *tty)
+{
+ struct psinfo p;
+ struct stat st;
+ char *path;
+ ssize_t bytes;
+ int f;
+ pid_t pgrp;
+
+ if ((f = open(tty, O_RDONLY)) < 0)
+ return (NULL);
+
+ if (fstat(f, &st) != 0 || ioctl(f, TIOCGPGRP, &pgrp) != 0) {
+ close(f);
+ return (NULL);
+ }
+ close(f);
+
+ xasprintf(&path, "/proc/%u/psinfo", (u_int) pgrp);
+ f = open(path, O_RDONLY);
+ free(path);
+ if (f < 0)
+ return (NULL);
+
+ bytes = read(f, &p, sizeof(p));
+ close(f);
+ if (bytes != sizeof(p))
+ return (NULL);
+
+ if (p.pr_ttydev != st.st_rdev)
+ return (NULL);
+
+ return (xstrdup(p.pr_fname));
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ static char target[MAXPATHLEN + 1];
+ char *path;
+ ssize_t n;
+ pid_t pgrp;
+
+ if ((pgrp = tcgetpgrp(fd)) == -1)
+ return (NULL);
+
+ xasprintf(&path, "/proc/%u/path/cwd", (u_int) pgrp);
+ n = readlink(path, target, MAXPATHLEN);
+ free(path);
+ if (n > 0) {
+ target[n] = '\0';
+ return (target);
+ }
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/osdep-unknown.c b/osdep-unknown.c
new file mode 100644
index 00000000..41f435bc
--- /dev/null
+++ b/osdep-unknown.c
@@ -0,0 +1,41 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <event.h>
+
+#include "tmux.h"
+
+char *
+osdep_get_name(unused int fd, unused char *tty)
+{
+ return (NULL);
+}
+
+char *
+osdep_get_cwd(int fd)
+{
+ return (NULL);
+}
+
+struct event_base *
+osdep_event_init(void)
+{
+ return (event_init());
+}
diff --git a/paste.c b/paste.c
index 2e89a5ef..7cbbbfb3 100644
--- a/paste.c
+++ b/paste.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <string.h>
-#include <vis.h>
#include "tmux.h"
diff --git a/resize.c b/resize.c
index b5196c1c..5c365dfe 100644
--- a/resize.c
+++ b/resize.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/screen-redraw.c b/screen-redraw.c
index 4601c6f3..a7bf81ff 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/screen-write.c b/screen-write.c
index 348065c6..3e836938 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/screen.c b/screen.c
index 754effc2..e92c6aa7 100644
--- a/screen.c
+++ b/screen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
diff --git a/server-client.c b/server-client.c
index f61912bc..77e6de78 100644
--- a/server-client.c
+++ b/server-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,7 +21,6 @@
#include <event.h>
#include <fcntl.h>
-#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
diff --git a/server-fn.c b/server-fn.c
index c0b005e8..566925f0 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/server-window.c b/server-window.c
index e82f0e36..4f5a5504 100644
--- a/server-window.c
+++ b/server-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/server.c b/server.c
index a07fa1fd..4bfa9185 100644
--- a/server.c
+++ b/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,7 +26,6 @@
#include <errno.h>
#include <event.h>
#include <fcntl.h>
-#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -154,7 +153,9 @@ server_start(int lockfd, char *lockfile)
start_time = time(NULL);
log_debug("socket path %s", socket_path);
+#ifdef HAVE_SETPROCTITLE
setproctitle("server (%s)", socket_path);
+#endif
server_fd = server_create_socket();
server_client_create(pair[1]);
diff --git a/session.c b/session.c
index c7b54a2b..74eb06a5 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,7 +19,6 @@
#include <sys/types.h>
#include <sys/time.h>
-#include <paths.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/signal.c b/signal.c
index f9546dc5..56333522 100644
--- a/signal.c
+++ b/signal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/status.c b/status.c
index 6ce0b871..f120c38a 100644
--- a/status.c
+++ b/status.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/tmux.1 b/tmux.1
index 0dc68bfe..05dfac61 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD$
+.\" $Id$
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate$
+.Dd $Mdocdate: March 25 2013 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm tmux
.Bk -words
-.Op Fl 28lCquv
+.Op Fl 28lCquvV
.Op Fl c Ar shell-command
.Op Fl f Ar file
.Op Fl L Ar socket-name
@@ -212,6 +212,10 @@ and
files in the current directory, where
.Em PID
is the PID of the server or client process.
+.It Fl V
+Report the
+.Nm
+version.
.It Ar command Op Ar flags
This specifies one of a set of commands used to control
.Nm ,
diff --git a/tmux.c b/tmux.c
index 368562f8..8ea91ebe 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,7 +22,6 @@
#include <errno.h>
#include <event.h>
#include <fcntl.h>
-#include <paths.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
@@ -30,7 +29,7 @@
#include "tmux.h"
-#ifdef DEBUG
+#if defined(DEBUG) && defined(__OpenBSD__)
extern char *malloc_options;
#endif
@@ -55,11 +54,15 @@ __dead void usage(void);
void parseenvironment(void);
char *makesocketpath(const char *);
+#ifndef HAVE___PROGNAME
+char *__progname = (char *) "tmux";
+#endif
+
__dead void
usage(void)
{
fprintf(stderr,
- "usage: %s [-28lquv] [-c shell-command] [-f file] [-L socket-name]\n"
+ "usage: %s [-28lquvV] [-c shell-command] [-f file] [-L socket-name]\n"
" [-S socket-path] [command [flags]]\n",
__progname);
exit(1);
@@ -237,14 +240,14 @@ main(int argc, char **argv)
char *s, *path, *label, *home, **var;
int opt, flags, quiet, keys;
-#ifdef DEBUG
+#if defined(DEBUG) && defined(__OpenBSD__)
malloc_options = (char *) "AFGJPX";
#endif
quiet = flags = 0;
label = path = NULL;
login_shell = (**argv == '-');
- while ((opt = getopt(argc, argv, "28c:Cdf:lL:qS:uUv")) != -1) {
+ while ((opt = getopt(argc, argv, "28c:Cdf:lL:qS:uUvV")) != -1) {
switch (opt) {
case '2':
flags |= IDENTIFY_256COLOURS;
@@ -264,6 +267,9 @@ main(int argc, char **argv)
else
flags |= IDENTIFY_CONTROL;
break;
+ case 'V':
+ printf("%s %s\n", __progname, VERSION);
+ exit(0);
case 'f':
free(cfg_file);
cfg_file = xstrdup(optarg);
@@ -390,10 +396,12 @@ main(int argc, char **argv)
strlcpy(socket_path, path, sizeof socket_path);
free(path);
+#ifdef HAVE_SETPROCTITLE
/* Set process title. */
setproctitle("%s (%s)", __progname, socket_path);
+#endif
/* Pass control to the client. */
- ev_base = event_init();
+ ev_base = osdep_event_init();
exit(client_main(argc, argv, flags));
}
diff --git a/tmux.h b/tmux.h
index 10da2bee..9c91d6a4 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,23 +23,19 @@
#include <sys/param.h>
#include <sys/time.h>
-#include <sys/queue.h>
-#include <sys/tree.h>
#include <sys/uio.h>
-#include <bitstring.h>
#include <event.h>
-#include <getopt.h>
-#include <imsg.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
-#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include "array.h"
+#include "compat.h"
+
extern char *__progname;
extern char **environ;
@@ -2329,9 +2325,10 @@ int utf8_append(struct utf8_data *, u_char);
u_int utf8_combine(const struct utf8_data *);
u_int utf8_split2(u_int, u_char *);
-/* procname.c */
-char *get_proc_name(int, char *);
-char *get_proc_cwd(int);
+/* osdep-*.c */
+char *osdep_get_name(int, char *);
+char *osdep_get_cwd(int);
+struct event_base *osdep_event_init(void);
/* log.c */
void log_open(int, const char *);
diff --git a/tools/256colors.pl b/tools/256colors.pl
new file mode 100644
index 00000000..c97c2be9
--- /dev/null
+++ b/tools/256colors.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+# Author: Todd Larason <jtl@molehill.org>
+# $XFree86: xc/programs/xterm/vttests/256colors2.pl,v 1.2 2002/03/26 01:46:43 dickey Exp $
+
+# use the resources for colors 0-15 - usually more-or-less a
+# reproduction of the standard ANSI colors, but possibly more
+# pleasing shades
+
+# colors 16-231 are a 6x6x6 color cube
+for ($red = 0; $red < 6; $red++) {
+ for ($green = 0; $green < 6; $green++) {
+ for ($blue = 0; $blue < 6; $blue++) {
+ printf("\x1b]4;%d;rgb:%2.2x/%2.2x/%2.2x\x1b\\",
+ 16 + ($red * 36) + ($green * 6) + $blue,
+ ($red ? ($red * 40 + 55) : 0),
+ ($green ? ($green * 40 + 55) : 0),
+ ($blue ? ($blue * 40 + 55) : 0));
+ }
+ }
+}
+
+# colors 232-255 are a grayscale ramp, intentionally leaving out
+# black and white
+for ($gray = 0; $gray < 24; $gray++) {
+ $level = ($gray * 10) + 8;
+ printf("\x1b]4;%d;rgb:%2.2x/%2.2x/%2.2x\x1b\\",
+ 232 + $gray, $level, $level, $level);
+}
+
+
+# display the colors
+
+# first the system ones:
+print "System colors:\n";
+for ($color = 0; $color < 8; $color++) {
+ print "\x1b[48;5;${color}m ";
+}
+print "\x1b[0m\n";
+for ($color = 8; $color < 16; $color++) {
+ print "\x1b[48;5;${color}m ";
+}
+print "\x1b[0m\n\n";
+
+# now the color cube
+print "Color cube, 6x6x6:\n";
+for ($green = 0; $green < 6; $green++) {
+ for ($red = 0; $red < 6; $red++) {
+ for ($blue = 0; $blue < 6; $blue++) {
+ $color = 16 + ($red * 36) + ($green * 6) + $blue;
+ print "\x1b[48;5;${color}m ";
+ }
+ print "\x1b[0m ";
+ }
+ print "\n";
+}
+
+
+# now the grayscale ramp
+print "Grayscale ramp:\n";
+for ($color = 232; $color < 256; $color++) {
+ print "\x1b[48;5;${color}m ";
+}
+print "\x1b[0m\n";
diff --git a/tools/UTF-8-demo.txt b/tools/UTF-8-demo.txt
new file mode 100644
index 00000000..4363f27b
--- /dev/null
+++ b/tools/UTF-8-demo.txt
@@ -0,0 +1,212 @@
+
+UTF-8 encoded sample plain-text file
+‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+Markus Kuhn [ˈmaʳkʊs kuːn] <http://www.cl.cam.ac.uk/~mgk25/> — 2002-07-25
+
+
+The ASCII compatible UTF-8 encoding used in this plain-text file
+is defined in Unicode, ISO 10646-1, and RFC 2279.
+
+
+Using Unicode/UTF-8, you can write in emails and source code things such as
+
+Mathematics and sciences:
+
+ ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫
+ ⎪⎢⎜│a²+b³ ⎟⎥⎪
+ ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪
+ ⎪⎢⎜⎷ c₈ ⎟⎥⎪
+ ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬
+ ⎪⎢⎜ ∞ ⎟⎥⎪
+ ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪
+ ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪
+ 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭
+
+Linguistics and dictionaries:
+
+ ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
+ Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
+
+APL:
+
+ ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
+
+Nicer typography in plain text files:
+
+ ╔══════════════════════════════════════════╗
+ ║ ║
+ ║ • ‘single’ and “double” quotes ║
+ ║ ║
+ ║ • Curly apostrophes: “We’ve been here” ║
+ ║ ║
+ ║ • Latin-1 apostrophe and accents: '´` ║
+ ║ ║
+ ║ • ‚deutsche‘ „Anführungszeichen“ ║
+ ║ ║
+ ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║
+ ║ ║
+ ║ • ASCII safety test: 1lI|, 0OD, 8B ║
+ ║ ╭─────────╮ ║
+ ║ • the euro symbol: │ 14.95 € │ ║
+ ║ ╰─────────╯ ║
+ ╚══════════════════════════════════════════╝
+
+Combining characters:
+
+ STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑
+
+Greek (in Polytonic):
+
+ The Greek anthem:
+
+ Σὲ γνωρίζω ἀπὸ τὴν κόψη
+ τοῦ σπαθιοῦ τὴν τρομερή,
+ σὲ γνωρίζω ἀπὸ τὴν ὄψη
+ ποὺ μὲ βία μετράει τὴ γῆ.
+
+ ᾿Απ᾿ τὰ κόκκαλα βγαλμένη
+ τῶν ῾Ελλήνων τὰ ἱερά
+ καὶ σὰν πρῶτα ἀνδρειωμένη
+ χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
+
+ From a speech of Demosthenes in the 4th century BC:
+
+ Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
+ ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
+ λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
+ τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
+ εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
+ πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
+ οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
+ οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
+ ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
+ τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
+ γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
+ προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
+ σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
+ τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
+ τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
+ τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
+
+ Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
+
+Georgian:
+
+ From a Unicode conference invitation:
+
+ გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
+ კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
+ ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
+ ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
+ ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
+ ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
+ ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
+
+Russian:
+
+ From a Unicode conference invitation:
+
+ Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
+ Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
+ Конференция соберет широкий круг экспертов по вопросам глобального
+ Интернета и Unicode, локализации и интернационализации, воплощению и
+ применению Unicode в различных операционных системах и программных
+ приложениях, шрифтах, верстке и многоязычных компьютерных системах.
+
+Thai (UCS Level 2):
+
+ Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
+ classic 'San Gua'):
+
+ [----------------------------|------------------------]
+ ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
+ สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
+ ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา
+ โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ
+ เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ
+ ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
+ พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้
+ ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
+
+ (The above is a two-column text. If combining characters are handled
+ correctly, the lines of the second column should be aligned with the
+ | character above.)
+
+Ethiopian:
+
+ Proverbs in the Amharic language:
+
+ ሰማይ አይታረስ ንጉሥ አይከሰስ።
+ ብላ ካለኝ እንደአባቴ በቆመጠኝ።
+ ጌጥ ያለቤቱ ቁምጥና ነው።
+ ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
+ የአፍ ወለምታ በቅቤ አይታሽም።
+ አይጥ በበላ ዳዋ ተመታ።
+ ሲተረጉሙ ይደረግሙ።
+ ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
+ ድር ቢያብር አንበሳ ያስር።
+ ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
+ እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
+ የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
+ ሥራ ከመፍታት ልጄን ላፋታት።
+ ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
+ የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
+ ተንጋሎ ቢተፉ ተመልሶ ባፉ።
+ ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
+ እግርህን በፍራሽህ ልክ ዘርጋ።
+
+Runes:
+
+ ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
+
+ (Old English, which transcribed into Latin reads 'He cwaeth that he
+ bude thaem lande northweardum with tha Westsae.' and means 'He said
+ that he lived in the northern land near the Western Sea.')
+
+Braille:
+
+ ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
+
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
+ ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
+ ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
+ ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
+ ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
+ ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
+
+ ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
+
+ ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
+ ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
+ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
+ ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
+ ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
+ ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
+ ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
+ ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
+
+ (The first couple of paragraphs of "A Christmas Carol" by Dickens)
+
+Compact font selection example text:
+
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
+ abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
+ –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
+ ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა
+
+Greetings in various languages:
+
+ Hello world, Καλημέρα κόσμε, コンニチハ
+
+Box drawing alignment tests: █
+ ▉
+ ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
+ ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
+ ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
+ ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
+ ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
+ ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
+ ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
+ ▝▀▘▙▄▟
diff --git a/tools/ansicode.txt b/tools/ansicode.txt
new file mode 100644
index 00000000..8767b9e7
--- /dev/null
+++ b/tools/ansicode.txt
@@ -0,0 +1,779 @@
+Summary of ANSI standards for ASCII terminals Joe Smith, 18-May-84
+
+Contents:
+ 1. Overview and Definitions
+ 2. General rules for interpreting an ESCape Sequence
+ 3. General rules for interpreting a Control Sequence
+ 4. C0 and C1 control codes in numeric order
+ 5. Two and three-character ESCape Sequences in numeric order
+ 6. Control Sequences in numeric order
+ 7. VT100 emulation requirements
+
+The VT100 USER GUIDE and ANSI standard X3.64-1979 both list the ANSI ESCape
+sequences in alphabetic order by mnemonic, but do not have a have a cross
+reference in order by ASCII code. This paper lists the combination of all
+definitions from the three ANSI standards in numeric order. For a description
+of the advantages of using these standards, see the article "Toward
+Standardized Video Terminals" in the April-1984 issue of BYTE magazine.
+
+ANSI X3.4-1977 defines the 7-bit ASCII character set (C0 and G0). It was
+written in 1968, revised in 1977, and explains the decisions made in laying out
+the ASCII code. In particular, it explains why ANSI chose to make ASCII
+incompatible with EBCDIC in order to make it self-consistant.
+
+ANSI X3.41-1974 introduces the idea of an 8-bit ASCII character set (C1 and G1
+in addition to the existing C0 and G0). It describes how to use the 8-bit
+features in a 7-bit environment. X3.41 defines the format of all ESCape
+sequences, but defines only the 3-character ones with a parameter character
+in the middle. These instruct the terminal how to interpret the C0, G0, C1,
+and G1 characters (such as by selecting different character-set ROMs).
+
+ Note: NAPLPS does videotex graphics by redefining the C1 set and
+ selecting alternate G0, G1, G2, and G3 sets.
+ See the February 1983 issue of BYTE magazine for details.
+
+ANSI X3.64-1979 defines the remaining ESCape sequences. It defines all the C1
+control characters, and specifies that certain two-character ESCape sequences
+in the 7-bit environment are to act exactly like the 8-bit C1 control set.
+X3.64 introduces the idea of a Control-Sequence, which starts with CSI
+character, has an indefinite length, and is terminated by an alphabetic
+character. The VT100 was one of the first terminals to implement this
+standard.
+
+Definitions:
+
+ Control Character - A single character with an ASCII code with the range
+ of 000 to 037 and 200 to 237 octal, 00 to 1F and 80 to 9F hex.
+
+ Escape Sequence - A two or three character string staring with ESCape.
+ (Four or more character strings are allowed but not defined.)
+
+ Control Sequence - A string starting with CSI (233 octal, 9B hex) or
+ with ESCape Left-Bracket, and terminated by an alphabetic character.
+ Any number of parameter characters (digits 0 to 9, semicolon, and
+ question mark) may appear within the Control Sequence. The terminating
+ character may be preceded by an intermediate character (such as space).
+ Character classifications:
+
+C0 Control 000-037 octal, 00-1F hex (G0 is 041-176 octal, 21-7E hex)
+SPACE 040+240 octal, 20+A0 hex Always and everywhere a blank space
+Intermediate 040-057 octal, 20-2F hex !"#$%&'()*+,-./
+Parameters 060-077 octal, 30-3F hex 0123456789:;<=>?
+Uppercase 100-137 octal, 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
+Lowercase 140-176 octal, 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~
+Alphabetic 100-176 octal, 40-7E hex (all of upper and lower case)
+Delete 177 octal, 7F hex Always and everywhere ignored
+C1 Control 200-237 octal, 80-9F hex 32 additional control characters
+G1 Displayable 241-376 octal, A1-FE hex 94 additional displayable characters
+Special 240+377 octal, A0+FF hex Same as SPACE and DELETE
+
+Note that in this paper, the terms uppercase, lowercase, and alphabetics
+include more characters than just A to Z.
+
+------------------------------------------------------------------------------
+
+General rules for interpreting an ESCape Sequence:
+
+ An ESCape Sequence starts with the ESC character (033 octal, 1B hex).
+The length of the ESCape Sequence depends on the character that immediately
+follows the ESCape.
+
+If the next character is
+ C0 control: Interpret it first, then resume processing ESCape sequence.
+ Example: CR, LF, XON, and XOFF work as normal within an ESCape sequence.
+ Intermediate: Expect zero or more intermediates, a parameter terminates
+ a private function, an alphabetic terminates a standard sequence.
+ Example: ESC ( A defines standard character set, ESC ( 0 a DEC set.
+ Parameter: End of a private 2-character escape sequence.
+ Example: ESC = sets special keypad mode, ESC > clears it.
+ Uppercase: Translate it into a C1 control character and act on it.
+ Example: ESC D does indexes down, ESC M indexes up. (CSI is special)
+ Lowercase: End of a standard 2-character escape sequence.
+ Example: ESC c resets the terminal.
+ Delete: Ignore it, and continue interpreting the ESCape sequence
+ C1 and G1: Treat the same as their 7-bit counterparts
+
+ Note that CSI is the two-character sequence ESCape left-bracket or the 8-bit
+C1 code of 233 octal, 9B hex. CSI introduces a Control Sequence, which
+continues until an alphabetic character is received.
+
+General rules for interpreting a Control Sequence:
+
+1) It starts with CSI, the Control Sequence Introducer.
+2) It contains any number of parameter characters (0123456789:;<=>?).
+3) It terminates with an alphabetic character.
+4) Intermediate characters (if any) immediately precede the terminator.
+
+If the first character after CSI is one of "<=>?" (074-077 octal, 3C-3F hex),
+then Control Sequence is to be interpreted according to private standards (such
+as setting and resetting modes not defined by ANSI). The terminal should
+expect any number of numeric parameters, separated by semicolons (073 octal,
+3B hex). Only after the terminating alphabetic character is received should
+the terminal act on the Control Sequence.
+
+=============================================================================
+ C0 set of 7-bit control characters (from ANSI X3.4-1977).
+
+Oct Hex Name * (* marks function used in DEC VT series or LA series terminals)
+--- -- - --- - --------------------------------------------------------------
+000 00 @ NUL * Null filler, terminal should ignore this character
+001 01 A SOH Start of Header
+002 02 B STX Start of Text, implied end of header
+003 03 C ETX End of Text, causes some terminal to respond with ACK or NAK
+004 04 D EOT End of Transmission
+005 05 E ENQ * Enquiry, causes terminal to send ANSWER-BACK ID
+006 06 F ACK Acknowledge, usually sent by terminal in response to ETX
+007 07 G BEL * Bell, triggers the bell, buzzer, or beeper on the terminal
+010 08 H BS * Backspace, can be used to define overstruck characters
+011 09 I HT * Horizontal Tabulation, move to next predetermined position
+012 0A J LF * Linefeed, move to same position on next line (see also NL)
+013 0B K VT * Vertical Tabulation, move to next predetermined line
+014 0C L FF * Form Feed, move to next form or page
+015 0D M CR * Carriage Return, move to first character of current line
+016 0E N SO * Shift Out, switch to G1 (other half of character set)
+017 0F O SI * Shift In, switch to G0 (normal half of character set)
+020 10 P DLE Data Link Escape, interpret next control character specially
+021 11 Q XON * (DC1) Terminal is allowed to resume transmitting
+022 12 R DC2 Device Control 2, causes ASR-33 to activate paper-tape reader
+023 13 S XOFF* (DC2) Terminal must pause and refrain from transmitting
+024 14 T DC4 Device Control 4, causes ASR-33 to deactivate paper-tape reader
+025 15 U NAK Negative Acknowledge, used sometimes with ETX and ACK
+026 16 V SYN Synchronous Idle, used to maintain timing in Sync communication
+027 17 W ETB End of Transmission block
+030 18 X CAN * Cancel (makes VT100 abort current escape sequence if any)
+031 19 Y EM End of Medium
+032 1A Z SUB * Substitute (VT100 uses this to display parity errors)
+033 1B [ ESC * Prefix to an ESCape sequence
+034 1C \ FS File Separator
+035 1D ] GS Group Separator
+036 1E ^ RS * Record Separator (sent by VT132 in block-transfer mode)
+037 1F _ US Unit Separator
+
+040 20 SP * Space (should never be defined to be otherwise)
+177 7F DEL * Delete, should be ignored by terminal
+
+==============================================================================
+ C1 set of 8-bit control characters (from ANSI X3.64-1979)
+
+Oct Hex Name * (* marks function used in DEC VT series or LA series terminals)
+--- -- - --- - --------------------------------------------------------------
+200 80 @ Reserved for future standardization
+201 81 A Reserved
+202 82 B Reserved
+203 83 C Reserved
+204 84 D IND * Index, moves down one line same column regardless of NL
+205 85 E NEL * NEw Line, moves done one line and to first column (CR+LF)
+206 86 F SSA Start of Selected Area to be sent to auxiliary output device
+207 87 G ESA End of Selected Area to be sent to auxiliary output device
+210 88 H HTS * Horizontal Tabulation Set at current position
+211 89 I HTJ Hor Tab Justify, moves string to next tab position
+212 8A J VTS Vertical Tabulation Set at current line
+213 8B K PLD Partial Line Down (subscript)
+214 8C L PLU Partial Line Up (superscript)
+215 8D M RI * Reverse Index, go up one line, reverse scroll if necessary
+216 8E N SS2 * Single Shift to G2
+217 8F O SS3 * Single Shift to G3 (VT100 uses this for sending PF keys)
+220 90 P DCS * Device Control String, terminated by ST (VT125 enters graphics)
+221 91 Q PU1 Private Use 1
+222 92 R PU2 Private Use 2
+223 93 S STS Set Transmit State
+224 94 T CCH Cancel CHaracter, ignore previous character
+225 95 U MW Message Waiting, turns on an indicator on the terminal
+226 96 V SPA Start of Protected Area
+227 97 W EPA End of Protected Area
+230 98 X Reserved for for future standard
+231 99 Y Reserved
+232 9A Z * Reserved, but causes DEC terminals to respond with DA codes
+233 9B [ CSI * Control Sequence Introducer (described in a seperate table)
+234 9C \ ST * String Terminator (VT125 exits graphics)
+235 9D ] OSC Operating System Command (reprograms intelligent terminal)
+236 9E ^ PM Privacy Message (password verification), terminated by ST
+237 9F _ APC Application Program Command (to word processor), term by ST
+
+==============================================================================
+ Character set selection sequences (from ANSI X3.41-1974)
+ All are 3 characters long (including the ESCape). Alphabetic characters
+ as 3rd character are defined by ANSI, parameter characters as 3rd character
+ may be interpreted differently by each terminal manufacturer.
+
+Oct Hex * (* marks function used in DEC VT series or LA series terminals)
+--- -- -- - ------------------------------------------------------------------
+040 20 ANNOUNCER - Determines whether to use 7-bit or 8-bit ASCII
+ A G0 only will be used. Ignore SI, SO, and G1.
+ B G0 and G1 used internally. SI and SO affect G0, G1 is ignored.
+ C G0 and G1 in an 8-bit only environment. SI and SO are ignored.
+ D G0 and G1 are used, SI and SO affect G0.
+ E
+ F * 7-bit transmission, VT240/PRO350 sends CSI as two characters ESC [
+ G * 8-bit transmission, VT240/PRO350 sends CSI as single 8-bit character
+041 21 ! Select C0 control set (choice of 63 standard, 16 private)
+042 22 " Select C1 control set (choice of 63 standard, 16 private)
+043 23 # Translate next character to a special single character
+ #3 * DECDHL1 - Double height line, top half
+ #4 * DECDHL2 - Double height line, bottom half
+ #5 * DECSWL - Single width line
+ #6 * DECDWL - Double width line
+ #7 * DECHCP - Make a hardcopy of the graphics screen (GIGI,VT125,VT241)
+ #8 * DECALN - Alignment display, fill screen with "E" to adjust focus
+044 24 $ MULTIBYTE CHARACTERS - Displayable characters require 2-bytes each
+045 25 % SPECIAL INTERPRETATION - Such as 9-bit data
+046 26 & Reserved for future standardization
+047 27 ' Reserved for future standardization
+050 28 ( * SCS - Select G0 character set (choice of 63 standard, 16 private)
+ (0 * DEC VT100 line drawing set (affects lowercase characters)
+ (1 * DEC Alternate character ROM set (RAM set on GIGI and VT220)
+ (2 * DEC Alternate character ROM set with line drawing
+ (5 * DEC Finnish on LA100
+ (6 * DEC Norwegian/Danish on LA100
+ (7 * DEC Swedish on LA100
+ (9 * DEC French Canadian
+ (< * DEC supplemental graphics (everything not in USASCII)
+ (A * UKASCII (British pound sign)
+ (B * USASCII (American pound sign)
+ (C * ISO Finnish on LA120
+ (E * ISO Norwegian/Danish on LA120
+ (H * ISO Swedish on LA120
+ (K * ISO German on LA100,LA120
+ (R * ISO French on LA100,LA120
+ (Y * ISO Italian on LA100
+ (Z * ISO Spanish on LA100
+051 29 ) * SCS - Select G1 character set (choice of 63 standard, 16 private)
+ * (same character sets as listed under G0)
+052 2A * * SCS - Select G2 character set
+ * (same character sets as listed under G0)
+053 2B + * SCS - Select G3 character set
+ * (same character sets as listed under G0)
+054 2C , SCS - Select G0 character set (additional 63+16 sets)
+055 2D - SCS - Select G1 character set (additional 63+16 sets)
+056 2E . SCS - Select G2 character set
+057 2F / SCS - Select G3 character set
+
+==============================================================================
+ Private two-character escape sequences (allowed by ANSI X3.41-1974)
+ These can be defined differently by each terminal manufacturer.
+
+Oct Hex * (* marks function used in DEC VT series or LA series terminals)
+--- -- - - ------------------------------------------------------------------
+060 30 0
+061 31 1 DECGON graphics on for VT105, DECHTS horiz tab set for LA34/LA120
+062 32 2 DECGOFF graphics off VT105, DECCAHT clear all horz tabs LA34/LA120
+063 33 3 DECVTS - set vertical tab for LA34/LA120
+064 34 4 DECCAVT - clear all vertical tabs for LA34/LA120
+065 35 5 * DECXMT - Host requests that VT132 transmit as if ENTER were pressed
+066 36 6
+067 37 7 * DECSC - Save cursor position and character attributes
+070 38 8 * DECRC - Restore cursor and attributes to previously saved position
+071 39 9
+072 3A :
+073 3B ;
+074 3C < * DECANSI - Switch from VT52 mode to VT100 mode
+075 3D = * DECKPAM - Set keypad to applications mode (ESCape instead of digits)
+076 3E > * DECKPNM - Set keypad to numeric mode (digits intead of ESCape seq)
+077 3F ?
+
+ DCS Device Control Strings used by DEC terminals (ends with ST)
+
+Pp = Start ReGIS graphics (VT125, GIGI, VT240, PRO350)
+Pq = Start SIXEL graphics (screen dump to LA34, LA100, screen load to VT125)
+Pr = SET-UP data for GIGI, $PrVC0$\ disables both visible cursors.
+Ps = Reprogram keys on the GIGI, $P0sDIR<CR>$\ makes keypad 0 send "DIR<CR>"
+ 0-9=digits on keypad, 10=ENTER, 11=minus, 12=comma, 13=period,
+ 14-17=PF1-PF4, 18-21=cursor keys. Enabled by $[?23h (PK1).
+Pt = Start VT105 graphics on a VT125
+
+==============================================================================
+
+ Standard two-character escape sequences (defined by ANSI X3.64-1979)
+
+100 40 @ See description of C1 control characters
+ An ESCape followed by one of these uppercase characters is translated
+ to an 8-bit C1 control character before being interpreted.
+220 90 P DCS - Device Control String, terminated by ST - see table above.
+133 5B [ CSI - Control Sequence Introducer - see table below.
+137 5F _ See description of C1 control characters
+
+==============================================================================
+
+ Indepenent control functions (from Appendix E of X3.64-1977).
+ These four controls have the same meaning regardless of the current
+ definition of the C0 and C1 control sets. Each control is a two-character
+ ESCape sequence, the 2nd character is lowercase.
+
+Oct Hex * (* marks function used in DEC VT series or LA series terminals)
+--- -- - - --------------------------------------------------------------------
+140 60 ` DMI - Disable Manual Input
+141 61 a INT - INTerrupt the terminal and do special action
+142 62 b EMI - Enable Manual Input
+143 63 c * RIS - Reset to Initial State (VT100 does a power-on reset)
+ ... The remaining lowercase characters are reserved by ANSI.
+153 6B k NAPLPS lock-shift G1 to GR
+154 6C l NAPLPS lock-shift G2 to GR
+155 6D m NAPLPS lock-shift G3 to GR
+156 6E n * LS2 - Shift G2 to GL (extension of SI) VT240,NAPLPS
+157 6F o * LS3 - Shift G3 to GL (extension of SO) VT240,NAPLPS
+ ... The remaining lowercase characters are reserved by ANSI.
+174 7C | * LS3R - VT240 lock-shift G3 to GR
+175 7D } * LS2R - VT240 lock-shift G2 to GR
+176 7E ~ * LS1R - VT240 lock-shift G1 to GR
+
+==============================================================================
+ Control Sequences (defined by ANSI X3.64-1979)
+
+Control Sequences are started by either ESC [ or CSI and are terminated by an
+"alphabetic" character (100 to 176 octal, 40 to 7E hex). Intermediate
+characters are space through slash (40 to 57 octal, 20 to 2F hex) and parameter
+characters are zero through question mark (60 to 77 octal, 30 to 3F hex,
+including digits and semicolon). Parameters consist of zero or more decimal
+numbers separated by semicolons. Leading zeros are optional, leading blanks
+are not allowed. If no digits precede the final character, the default
+parameter is used. Many functions treat a parameter of 0 as if it were 1.
+
+Oct Hex * (* marks function used in DEC VT series or LA series terminals)
+--- -- - - --------------------------------------------------------------------
+100 40 @ ICH - Insert CHaracter
+ [10@ = Make room for 10 characters at current position
+101 41 A * CUU - CUrsor Up
+ * [A = Move up one line, stop at top of screen, [9A = move up 9
+102 42 B * CUD - CUrsor Down
+ * [B = Move down one line, stop at bottom of screen
+103 43 C * CUF - CUrsor Forward
+ * [C = Move forward one position, stop at right edge of screen
+104 44 D * CUB - CUrsor Backward
+ * [D = Same as BackSpace, stop at left edge of screen
+105 45 E CNL - Cursor to Next Line
+ [5E = Move to first position of 5th line down
+106 46 F CPL - Cursor to Previous Line
+ [5F = Move to first position of 5th line previous
+107 47 G CHA - Cursor Horizontal position Absolute
+ [40G = Move to column 40 of current line
+110 48 H * CUP - CUrsor Position
+ * [H = Home, [24;80H = Row 24, Column 80
+111 49 I CHT - Cursor Horizontal Tabulation
+ [I = Same as HT (Control-I), [3I = Go forward 3 tabs
+112 4A J * ED - Erase in Display (cursor does not move)
+ * [J = [0J = Erase from current position to end (inclusive)
+ * [1J = Erase from beginning to current position (inclusive)
+ * [2J = Erase entire display
+ * [?0J = Selective erase in display ([?1J, [?2J similar)
+113 4B K * EL - Erase in Line (cursor does not move)
+ * [K = [0K = Erase from current position to end (inclusive)
+ * [1K = Erase from beginning to current position
+ * [2K = Erase entire current line
+ * [?0K = Selective erase to end of line ([?1K, [?2K similar)
+114 4C L * IL - Insert Line, current line moves down (VT102 series)
+ [3L = Insert 3 lines if currently in scrolling region
+115 4D M * DL - Delete Line, lines below current move up (VT102 series)
+ [2M = Delete 2 lines if currently in scrolling region
+116 4E N EF - Erase in Field (as bounded by protected fields)
+ [0N, [1N, [2N act like [L but within currend field
+117 4F O EA - Erase in qualified Area (defined by DAQ)
+ [0O, [1O, [2O act like [J but within current area
+120 50 P * DCH - Delete Character, from current position to end of field
+ [4P = Delete 4 characters, VT102 series
+121 51 Q SEM - Set Editing extent Mode (limits ICH and DCH)
+ [0Q = [Q = Insert/delete character affects rest of display
+ [1Q = ICH/DCH affect the current line only
+ [2Q = ICH/DCH affect current field (between tab stops) only
+ [3Q = ICH/DCH affect qualified area (between protected fields)
+122 52 R * CPR - Cursor Position Report (from terminal to host)
+ * [24;80R = Cursor is positioned at line 24 column 80
+123 53 S SU - Scroll up, entire display is moved up, new lines at bottom
+ [3S = Move everything up 3 lines, bring in 3 new lines
+124 54 T SD - Scroll down, new lines inserted at top of screen
+ [4T = Scroll down 4, bring previous lines back into view
+125 55 U NP - Next Page (if terminal has more than 1 page of memory)
+ [2U = Scroll forward 2 pages
+126 56 V PP - Previous Page (if terminal remembers lines scrolled off top)
+ [1V = Scroll backward 1 page
+127 57 W CTC - Cursor Tabulation Control
+ [0W = Set horizontal tab for current line at current position
+ [1W = Set vertical tab stop for current line of current page
+ [2W = Clear horiz tab stop at current position of current line
+ [3W = Clear vert tab stop at current line of current page
+ [4W = Clear all horiz tab stops on current line only
+ [5W = Clear all horiz tab stops for the entire terminal
+ [6W = Clear all vert tabs stops for the entire terminal
+130 58 X ECH - Erase CHaracter
+ [4X = Change next 4 characters to "erased" state
+131 59 Y CVT - Cursor Vertical Tab
+ [2Y = Move forward to 2nd following vertical tab stop
+132 5A Z CBT - Cursor Back Tab
+ [3Z = Move backwards to 3rd previous horizontal tab stop
+133 5B [ Reserved for future standardization left bracket
+134 5C \ Reserved reverse slant
+135 5D ] Reserved right bracket
+136 5E ^ Reserved circumflex
+137 5F _ Reserved underscore
+140 60 ` * HPA - Horizontal Position Absolute (depends on PUM)
+ [720` = Move to 720 decipoints (1 inch) from left margin
+ * [80` = Move to column 80 on LA120
+141 61 a * HPR - Horizontal Position Relative (depends on PUM)
+ [360a = Move 360 decipoints (1/2 inch) from current position
+ * [40a = Move 40 columns to right of current position on LA120
+142 62 b REP - REPeat previous displayable character
+ [80b = Repeat character 80 times
+143 63 c * DA - Device Attributes
+ * [c = Terminal will identify itself
+ * [?1;2c = Terminal is saying it is a VT100 with AVO
+ * [>0c = Secondary DA request (distinguishes VT240 from VT220)
+144 64 d * VPA - Vertical Position Absolute (depends on PUM)
+ [90d = Move to 90 decipoints (1/8 inch) from top margin
+ * [10d = Move to line 10 if before that else line 10 next page
+145 65 e * VPR - Vertical Position Relative (depends on PUM)
+ [720e = Move 720 decipoints (1 inch) down from current position
+ * [6e = Advance 6 lines forward on LA120
+146 66 f * HVP - Horizontal and Vertical Position (depends on PUM)
+ [720,1440f = Move to 1 inch down and 2 inches over (decipoints)
+ * [24;80f = Move to row 24 column 80 if PUM is set to character
+147 67 g * TBC - Tabulation Clear
+ * [0g = Clear horizontal tab stop at current position
+ * [1g = Clear vertical tab stop at current line (LA120)
+ * [2g = Clear all horizontal tab stops on current line only LA120
+ * [3g = Clear all horizontal tab stops in the terminal
+150 68 h * SM - Set Mode (. means permanently set on VT100)
+ [0h = Error, this command is ignored
+ * [1h = GATM - Guarded Area Transmit Mode, send all (VT132)
+ [2h = KAM - Keyboard Action Mode, disable keyboard input
+ [3h = CRM - Control Representation Mode, show all control chars
+ * [4h = IRM - Insertion/Replacement Mode, set insert mode (VT102)
+ [5h = SRTM - Status Report Transfer Mode, report after DCS
+ * [6h = ERM - ERasure Mode, erase protected and unprotected
+ [7h = VEM - Vertical Editing Mode, IL/DL affect previous lines
+ [8h, [9h are reserved
+ [10h = HEM - Horizontal Editing mode, ICH/DCH/IRM go backwards
+ [11h = PUM - Positioning Unit Mode, use decipoints for HVP/etc
+ . [12h = SRM - Send Receive Mode, transmit without local echo
+ [13h = FEAM - Format Effector Action Mode, FE's are stored
+ [14h = FETM - Format Effector Transfer Mode, send only if stored
+ [15h = MATM - Multiple Area Transfer Mode, send all areas
+ * [16h = TTM - Transmit Termination Mode, send scrolling region
+ [17h = SATM - Send Area Transmit Mode, send entire buffer
+ [18h = TSM - Tabulation Stop Mode, lines are independent
+ [19h = EBM - Editing Boundry Mode, all of memory affected
+ * [20h = LNM - Linefeed Newline Mode, LF interpreted as CR LF
+ * [?1h = DECCKM - Cursor Keys Mode, send ESC O A for cursor up
+ * [?2h = DECANM - ANSI Mode, use ESC < to switch VT52 to ANSI
+ * [?3h = DECCOLM - COLumn mode, 132 characters per line
+ * [?4h = DECSCLM - SCrolL Mode, smooth scrolling
+ * [?5h = DECSCNM - SCreeN Mode, black on white background
+ * [?6h = DECOM - Origin Mode, line 1 is relative to scroll region
+ * [?7h = DECAWM - AutoWrap Mode, start newline after column 80
+ * [?8h = DECARM - Auto Repeat Mode, key will autorepeat
+ * [?9h = DECINLM - INterLace Mode, interlaced for taking photos
+ * [?10h = DECEDM - EDit Mode, VT132 is in EDIT mode
+ * [?11h = DECLTM - Line Transmit Mode, ignore TTM, send line
+ [?12h = ?
+ * [?13h = DECSCFDM - Space Compression/Field Delimiting on,
+ * [?14h = DECTEM - Transmit Execution Mode, transmit on ENTER
+ [?15h = ?
+ * [?16h = DECEKEM - Edit Key Execution Mode, EDIT key is local
+ [?17h = ?
+ * [?18h = DECPFF - Print FormFeed mode, send FF after printscreen
+ * [?19h = DECPEXT - Print Extent mode, print entire screen
+ * [?20h = OV1 - Overstrike, overlay characters on GIGI
+ * [?21h = BA1 - Local BASIC, GIGI to keyboard and screen
+ * [?22h = BA2 - Host BASIC, GIGI to host computer
+ * [?23h = PK1 - GIGI numeric keypad sends reprogrammable sequences
+ * [?24h = AH1 - Autohardcopy before erasing or rolling GIGI screen
+ * [?29h = - Use only the proper pitch for the LA100 font
+ * [?38h = DECTEK - TEKtronix mode graphics
+151 69 i * MC - Media Copy (printer port on VT102)
+ * [0i = Send contents of text screen to printer
+ [1i = Fill screen from auxiliary input (printer's keyboard)
+ [2i = Send screen to secondary output device
+ [3i = Fill screen from secondary input device
+ * [4i = Turn on copying received data to primary output (VT125)
+ * [4i = Received data goes to VT102 screen, not to its printer
+ * [5i = Turn off copying received data to primary output (VT125)
+ * [5i = Received data goes to VT102's printer, not its screen
+ * [6i = Turn off copying received data to secondary output (VT125)
+ * [7i = Turn on copying received data to secondary output (VT125)
+ * [?0i = Graphics screen dump goes to graphics printer VT125,VT240
+ * [?1i = Print cursor line, terminated by CR LF
+ * [?2i = Graphics screen dump goes to host computer VT125,VT240
+ * [?4i = Disable auto print
+ * [?5i = Auto print, send a line at a time when linefeed received
+152 6A j Reserved for future standardization
+153 6B k Reserved for future standardization
+154 6C l * RM - Reset Mode (. means permanently reset on VT100)
+ * [1l = GATM - Transmit only unprotected characters (VT132)
+ . [2l = KAM - Enable input from keyboard
+ . [3l = CRM - Control characters are not displayable characters
+ * [4l = IRM - Reset to replacement mode (VT102)
+ . [5l = SRTM - Report only on command (DSR)
+ * [6l = ERM - Erase only unprotected fields
+ . [7l = VEM - IL/DL affect lines after current line
+ [8l, [9l are reserved
+ . [10l = HEM - ICH and IRM shove characters forward, DCH pulls
+ . [11l = PUM - Use character positions for HPA/HPR/VPA/VPR/HVP
+ [12l = SRM - Local echo - input from keyboard sent to screen
+ . [13l = FEAM - HPA/VPA/SGR/etc are acted upon when received
+ . [14l = FETM - Format Effectors are sent to the printer
+ [15l = MATM - Send only current area if SATM is reset
+ * [16l = TTM - Transmit partial page, up to cursor position
+ [17l = SATM - Transmit areas bounded by SSA/ESA/DAQ
+ . [18l = TSM - Setting a tab stop on one line affects all lines
+ . [19l = EBM - Insert does not overflow to next page
+ * [20l = LNM - Linefeed does not change horizontal position
+ * [?1l = DECCKM - Cursor keys send ANSI cursor position commands
+ * [?2l = DECANM - Use VT52 emulation instead of ANSI mode
+ * [?3l = DECCOLM - 80 characters per line (erases screen)
+ * [?4l = DECSCLM - Jump scrolling
+ * [?5l = DECSCNM - Normal screen (white on black background)
+ * [?6l = DECOM - Line numbers are independent of scrolling region
+ * [?7l = DECAWM - Cursor remains at end of line after column 80
+ * [?8l = DECARM - Keys do not repeat when held down
+ * [?9l = DECINLM - Display is not interlaced to avoid flicker
+ * [?10l = DECEDM - VT132 transmits all key presses
+ * [?11l = DECLTM - Send page or partial page depending on TTM
+ [?12l = ?
+ * [?13l = DECSCFDM - Don't suppress trailing spaces on transmit
+ * [?14l = DECTEM - ENTER sends ESC S (STS) a request to send
+ [?15l = ?
+ * [?16l = DECEKEM - EDIT key transmits either $[10h or $[10l
+ [?17l = ?
+ * [?18l = DECPFF - Don't send a formfeed after printing screen
+ * [?19l = DECPEXT - Print only the lines within the scroll region
+ * [?20l = OV0 - Space is destructive, replace not overstrike, GIGI
+ * [?21l = BA0 - No BASIC, GIGI is On-Line or Local
+ * [?22l = BA0 - No BASIC, GIGI is On-Line or Local
+ * [?23l = PK0 - Ignore reprogramming on GIGI keypad and cursors
+ * [?24l = AH0 - No auto-hardcopy when GIGI screen erased
+ * [?29l = Allow all character pitches on the LA100
+ * [?38l = DECTEK - Ignore TEKtronix graphics commands
+155 6D m * SGR - Set Graphics Rendition (affects character attributes)
+ * [0m = Clear all special attributes
+ * [1m = Bold or increased intensity
+ * [2m = Dim or secondary color on GIGI (superscript on XXXXXX)
+ [3m = Italic (subscript on XXXXXX)
+ * [4m = Underscore, [0;4m = Clear, then set underline only
+ * [5m = Slow blink
+ [6m = Fast blink (overscore on XXXXXX)
+ * [7m = Negative image, [0;1;7m = Bold + Inverse
+ [8m = Concealed (do not display character echoed locally)
+ [9m = Reserved for future standardization
+ * [10m = Select primary font (LA100)
+ * [11m - [19m = Selete alternate font (LA100 has 11 thru 14)
+ [20m = FRAKTUR (whatever that means)
+ * [22m = Cancel bold or dim attribute only (VT220)
+ * [24m = Cancel underline attribute only (VT220)
+ * [25m = Cancel fast or slow blink attribute only (VT220)
+ * [27m = Cancel negative image attribute only (VT220)
+ * [30m = Write with black, [40m = Set background to black (GIGI)
+ * [31m = Write with red, [41m = Set background to red
+ * [32m = Write with green, [42m = Set background to green
+ * [33m = Write with yellow, [43m = Set background to yellow
+ * [34m = Write with blue, [44m = Set background to blue
+ * [35m = Write with magenta, [45m = Set background to magenta
+ * [36m = Write with cyan, [46m = Set background to cyan
+ * [37m = Write with white, [47m = Set background to white
+ [38m, [39m, [48m, [49m are reserved
+156 6E n * DSR - Device Status Report
+ * [0n = Terminal is ready, no malfunctions detected
+ [1n = Terminal is busy, retry later
+ [2n = Terminal is busy, it will send DSR when ready
+ * [3n = Malfunction, please try again
+ [4n = Malfunction, terminal will send DSR when ready
+ * [5n = Command to terminal to report its status
+ * [6n = Command to terminal requesting cursor position (CPR)
+ * [?15n = Command to terminal requesting printer status, returns
+ [?10n = OK, [?11n = not OK, [?13n = no printer.
+ * [?25n = "Are User Defined Keys Locked?" (VT220)
+157 6F o DAQ - Define Area Qualification starting at current position
+ [0o = Accept all input, transmit on request
+ [1o = Protected and guarded, accept no input, do not transmit
+ [2o = Accept any printing character in this field
+ [3o = Numeric only field
+ [4o = Alphabetic (A-Z and a-z) only
+ [5o = Right justify in area
+ [3;6o = Zero fill in area
+ [7o = Set horizontal tab stop, this is the start of the field
+ [8o = Protected and unguarded, accept no input, do transmit
+ [9o = Space fill in area
+
+==============================================================================
+
+ Private Control Sequences (allowed by ANSI X3.41-1974).
+ These take parameter strings and terminate with the last half of lowercase.
+
+Oct Hex * (* marks function used in DEC VT series or LA series terminals)
+--- -- - - --------------------------------------------------------------------
+160 70 p * DECSTR - Soft Terminal Reset
+ [!p = Soft Terminal Reset
+161 71 q * DECLL - Load LEDs
+ [0q = Turn off all, [?1;4q turns on L1 and L4, etc
+ [154;155;157q = VT100 goes bonkers
+ [2;23!q = Partial screen dump from GIGI to graphics printer
+ [0"q = DECSCA Select Character Attributes off
+ [1"q = DECSCA - designate set as non-erasable
+ [2"q = DECSCA - designate set as erasable
+162 72 r * DECSTBM - Set top and bottom margins (scroll region on VT100)
+ [4;20r = Set top margin at line 4 and bottom at line 20
+163 73 s * DECSTRM - Set left and right margins on LA100,LA120
+ [5;130s = Set left margin at column 5 and right at column 130
+164 74 t * DECSLPP - Set physical lines per page
+ [66t = Paper has 66 lines (11 inches at 6 per inch)
+165 75 u * DECSHTS - Set many horizontal tab stops at once on LA100
+ [9;17;25;33;41;49;57;65;73;81u = Set standard tab stops
+166 76 v * DECSVTS - Set many vertical tab stops at once on LA100
+ [1;16;31;45v = Set vert tabs every 15 lines
+167 77 w * DECSHORP - Set horizontal pitch on LAxxx printers
+ [1w = 10 characters per inch, [2w = 12 characters per inch
+ [0w=10, [3w=13.2, [4w=16.5, [5w=5, [6w=6, [7w=6.6, [8w=8.25
+170 78 x * DECREQTPARM - Request terminal parameters
+ [3;5;2;64;64;1;0x = Report, 7 bit Even, 1200 baud, 1200 baud
+171 79 y * DECTST - Invoke confidence test
+ [2;1y = Power-up test on VT100 series (and VT100 part of VT125)
+ [3;1y = Power-up test on GIGI (VK100)
+ [4;1y = Power-up test on graphics portion of VT125
+172 7A z * DECVERP - Set vertical pitch on LA100
+ [1z = 6 lines per inch, [2z = 8 lines per inch
+ [0z=6, [3z=12, [4z=3, [5z=3, [6z=4
+173 7B { Private
+174 7C | * DECTTC - Transmit Termination Character
+ [0| = No extra characters, [1| = terminate with FF
+175 7D } * DECPRO - Define protected field on VT132
+ [0} = No protection, [1;4;5;7} = Any attribute is protected
+ [254} = Characters with no attributes are protected
+176 7E ~ * DECKEYS - Sent by special function keys
+ [1~=FIND, [2~=INSERT, [3~=REMOVE, [4~=SELECT, [5~=PREV, [6~=NEXT
+ [17~=F6...[34~=F20 ([23~=ESC,[24~=BS,[25~=LF,[28~=HELP,[29~=DO)
+177 7F DELETE is always ignored
+
+==============================================================================
+ Control Sequences with intermediate characters (from ANSI X3.64-1979).
+ Note that there is a SPACE character before the terminating alphabetic.
+
+Oct Hex * (* marks function used in DEC VT series or LA series terminals)
+--- -- - - --------------------------------------------------------------------
+100 40 @ SL - Scroll Left
+ [4 @ = Move everything over 4 columns, 4 new columns at right
+101 41 A SR - Scroll Right
+ [2 A = Move everything over 2 columns, 2 new columns at left
+102 42 B GSM - Graphic Size Modification
+ [110;50 B = Make 110% high, 50% wide
+103 43 C GSS - Graphic Size Selection
+ [120 C = Make characters 120 decipoints (1/6 inch) high
+104 44 D FNT - FoNT selection (used by SGR, [10m thru [19m)
+ [0;23 D = Make primary font be registered font #23
+105 45 E TSS - Thin Space Specification
+ [36 E = Define a thin space to be 36 decipoints (1/20 inch)
+106 46 F JFY - JustiFY, done by the terminal/printer
+ [0 E = No justification
+ [1 E = Fill, bringing words up from next line if necessary
+ [2 E = Interword spacing, adjust spaces between words
+ [3 E = Letter spacing, adjust width of each letter
+ [4 E = Use hyphenation
+ [5 E = Flush left margin
+ [6 E = Center following text between margins (until [0 E)
+ [7 E = Flush right margin
+ [8 E = Italian form (underscore instead of hyphen)
+107 47 G SPI - SPacing Increment (in decipoints)
+ [120;72 G = 6 per inch vertical, 10 per inch horizontal
+110 48 H QUAD- Do quadding on current line of text (typography)
+ [0 H = Flush left, [1 H = Flush left and fill with leader
+ [2 H = Center, [3 H = Center and fill with leader
+ [4 H = Flush right, [5 H = Flush right and fill with leader
+111 49 I Reserved for future standardization
+157 67 o Reserved for future standardization
+160 70 p Private use
+ ... May be defined by the printer manufacturer
+176 7E ~ Private use
+177 7F DELETE is always ignored
+
+==============================================================================
+ Minimum requirements for VT100 emulation:
+
+1) To act as a passive display, implement the 4 cursor commands, the 2 erase
+ commands, direct cursor addressing, and at least inverse characters.
+ The software should be capable of handling strings with 16 numeric parameters
+ with values in the range of 0 to 255.
+
+ [A Move cursor up one row, stop if a top of screen
+ [B Move cursor down one row, stop if at bottom of screen
+ [C Move cursor forward one column, stop if at right edge of screen
+ [D Move cursor backward one column, stop if at left edge of screen
+ [H Home to row 1 column 1 (also [1;1H)
+ [J Clear from current position to bottom of screen
+ [K Clear from current position to end of line
+ [24;80H Position to line 24 column 80 (any line 1 to 24, any column 1 to 132)
+ [0m Clear attributes to normal characters
+ [7m Add the inverse video attribute to succeeding characters
+ [0;7m Set character attributes to inverse video only
+
+2) To enter data in VT100 mode, implement the 4 cursor keys and the 4 PF keys.
+ It must be possible to enter ESC, TAB, BS, DEL, and LF from the keyboard.
+
+ [A Sent by the up-cursor key (alternately ESC O A)
+ [B Sent by the down-cursor key (alternately ESC O B)
+ [C Sent by the right-cursor key (alternately ESC O C)
+ [D Sent by the left-cursor key (alternately ESC O D)
+ OP PF1 key sends ESC O P
+ OQ PF2 key sends ESC O Q
+ OR PF3 key sends ESC O R
+ OS PF3 key sends ESC O S
+ [c Request for the terminal to identify itself
+ [?1;0c VT100 with memory for 24 by 80, inverse video character attribute
+ [?1;2c VT100 capable of 132 column mode, with bold+blink+underline+inverse
+
+3) When doing full-screen editing on a VT100, implement directed erase, the
+ numeric keypad in applications mode, and the limited scrolling region.
+ The latter is needed to do insert/delete line functions without rewriting
+ the screen.
+
+ [0J Erase from current position to bottom of screen inclusive
+ [1J Erase from top of screen to current position inclusive
+ [2J Erase entire screen (without moving the cursor)
+ [0K Erase from current position to end of line inclusive
+ [1K Erase from beginning of line to current position inclusive
+ [2K Erase entire line (without moving cursor)
+ [12;24r Set scrolling region to lines 12 thru 24. If a linefeed or an
+ INDex is received while on line 24, the former line 12 is deleted
+ and rows 13-24 move up. If a RI (reverse Index) is received while
+ on line 12, a blank line is inserted there as rows 12-13 move down.
+ All VT100 compatible terminals (except GIGI) have this feature.
+ ESC = Set numeric keypad to applications mode
+ ESC > Set numeric keypad to numbers mode
+ OA Up-cursor key sends ESC O A after ESC = ESC [ ? 1 h
+ OB Down-cursor key sends ESC O B " " "
+ OC Right-cursor key sends ESC O B " " "
+ OB Left-cursor key sends ESC O B " " "
+ OM ENTER key sends ESC O M after ESC =
+ Ol COMMA on keypad sends ESC O l " " (that's lowercase L)
+ Om MINUS on keypad sends ESC O m " "
+ Op ZERO on keypad sends ESC O p " "
+ Oq ONE on keypad sends ESC O q " "
+ Or TWO on keypad sends ESC O r " "
+ Os THREE on keypad sends ESC O s " "
+ Ot FOUR on keypad sends ESC O t " "
+ Ou FIVE on keypad sends ESC O u " "
+ Ov SIX on keypad sends ESC O v " "
+ Ow SEVEN on keypad sends ESC O w " "
+ Ox EIGHT on keypad sends ESC O x " "
+ Oy NINE on keypad sends ESC O y " "
+
+4) If the hardware is capable of double width/double height:
+
+ #3 Top half of a double-width double-height line
+ #4 Bottom half of a double-width double-height line
+ #5 Make line single-width (lines are set this way when cleared by ESC [ J)
+ #6 Make line double-width normal height (40 or 66 characters)
+
+5) If the terminal emulator is capable of insert/delete characters,
+insert/delete lines, insert/replace mode, and can do a full-screen dump to
+the printer (in text mode), then it should identify itself as a VT102
+
+ [c Request for the terminal to identify itself
+ [?6c VT102 (printer port, 132 column mode, and ins/del standard)
+ [1@ Insert a blank character position (shift line to the right)
+ [1P Delete a character position (shift line to the left)
+ [1L Insert blank line at current row (shift screen down)
+ [1M Delete the current line (shift screen up)
+ [4h Set insert mode, new characters shove existing ones to the right
+ [4l Reset insert mode, new characters replace existing ones
+ [0i Print screen (all 24 lines) to the printer
+ [4i All received data goes to the printer (nothing to the screen)
+ [5i All received data goes to the screen (nothing to the printer)
+
+
+[End of ANSICODE.TXT]
diff --git a/tools/check-compat.sh b/tools/check-compat.sh
new file mode 100644
index 00000000..b7603a80
--- /dev/null
+++ b/tools/check-compat.sh
@@ -0,0 +1,5 @@
+# $Id$
+
+grep "#include" compat.h|while read line; do
+ grep "$line" *.[ch] compat/*.[ch]
+done
diff --git a/tools/cmp-cvs.sh b/tools/cmp-cvs.sh
new file mode 100644
index 00000000..104ded6b
--- /dev/null
+++ b/tools/cmp-cvs.sh
@@ -0,0 +1,12 @@
+# $Id$
+
+rm diff.out
+touch diff.out
+
+for i in *.[ch]; do
+ diff -u $i /usr/src/usr.bin/tmux/$i >diff.tmp
+ set -- `wc -l diff.tmp`
+ [ $1 -eq 8 ] && continue
+ echo $i
+ cat diff.tmp >>diff.out
+done
diff --git a/tools/fix-ids.sh b/tools/fix-ids.sh
new file mode 100644
index 00000000..4621d2b4
--- /dev/null
+++ b/tools/fix-ids.sh
@@ -0,0 +1,8 @@
+# $Id$
+
+for i in *.[ch] tmux.1; do
+ (head -1 $i|grep '$OpenBSD' >/dev/null) || continue
+ mv $i $i~ || exit
+ sed 's/\$OpenBSD.* \$/$\Id$/' $i~ >$i || exit
+ echo $i
+done
diff --git a/tools/fuzz.c b/tools/fuzz.c
new file mode 100644
index 00000000..39a2a4db
--- /dev/null
+++ b/tools/fuzz.c
@@ -0,0 +1,31 @@
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+ time_t t;
+ int i;
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ t = time(NULL);
+ srandom((u_int) t);
+
+ for (;;) {
+ putchar('\033');
+
+ for (i = 0; i < random() % 25; i++) {
+ if (i > 22)
+ putchar(';');
+ else
+ putchar(random() % 256);
+ }
+
+ /* usleep(100); */
+ }
+}
diff --git a/tools/putty-utf8.sh b/tools/putty-utf8.sh
new file mode 100644
index 00000000..73cb5fb1
--- /dev/null
+++ b/tools/putty-utf8.sh
@@ -0,0 +1 @@
+echo -ne \\033%G\\033[?47h\\033%G\\033[?47l
diff --git a/tty-acs.c b/tty-acs.c
index 297c51ac..e85888c3 100644
--- a/tty-acs.c
+++ b/tty-acs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/tty-keys.c b/tty-keys.c
index 26edbf32..3055f399 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/tty-term.c b/tty-term.c
index c827a444..95cb5db7 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,12 +18,15 @@
#include <sys/types.h>
+#ifdef HAVE_CURSES_H
#include <curses.h>
+#else
+#include <ncurses.h>
+#endif
#include <fnmatch.h>
#include <stdlib.h>
#include <string.h>
#include <term.h>
-#include <vis.h>
#include "tmux.h"
@@ -386,7 +389,10 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
tty_term_override(term, overrides);
/* Delete curses data. */
+#if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \
+ (NCURSES_VERSION_MAJOR == 5 && NCURSES_VERSION_MINOR > 6)
del_curterm(cur_term);
+#endif
/* These are always required. */
if (!tty_term_has(term, TTYC_CLEAR)) {
@@ -489,25 +495,25 @@ tty_term_string(struct tty_term *term, enum tty_code_code code)
const char *
tty_term_string1(struct tty_term *term, enum tty_code_code code, int a)
{
- return (tparm((char *) tty_term_string(term, code), a));
+ return (tparm((char *) tty_term_string(term, code), a, 0, 0, 0, 0, 0, 0, 0, 0));
}
const char *
tty_term_string2(struct tty_term *term, enum tty_code_code code, int a, int b)
{
- return (tparm((char *) tty_term_string(term, code), a, b));
+ return (tparm((char *) tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
}
const char *
tty_term_ptr1(struct tty_term *term, enum tty_code_code code, const void *a)
{
- return (tparm((char *) tty_term_string(term, code), a));
+ return (tparm((char *) tty_term_string(term, code), a, 0, 0, 0, 0, 0, 0, 0, 0));
}
const char *
tty_term_ptr2(struct tty_term *term, enum tty_code_code code, const void *a, const void *b)
{
- return (tparm((char *) tty_term_string(term, code), a, b));
+ return (tparm((char *) tty_term_string(term, code), a, b, 0, 0, 0, 0, 0, 0, 0));
}
int
diff --git a/tty.c b/tty.c
index 75a2f657..ab75d948 100644
--- a/tty.c
+++ b/tty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/utf8.c b/utf8.c
index b276d872..88d847a6 100644
--- a/utf8.c
+++ b/utf8.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -135,7 +135,9 @@ struct utf8_width_entry utf8_width_table[] = {
{ 0x0135f, 0x0135f, 0, NULL, NULL },
{ 0x01a17, 0x01a18, 0, NULL, NULL },
{ 0x006e7, 0x006e8, 0, NULL, NULL },
+#ifndef __APPLE__
{ 0x03099, 0x0309a, 0, NULL, NULL },
+#endif
{ 0x00b4d, 0x00b4d, 0, NULL, NULL },
{ 0x00ce2, 0x00ce3, 0, NULL, NULL },
{ 0x00bcd, 0x00bcd, 0, NULL, NULL },
diff --git a/window-choose.c b/window-choose.c
index 792224c1..3c68d101 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/window-clock.c b/window-clock.c
index 8ec1671e..61cf1502 100644
--- a/window-clock.c
+++ b/window-clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/window-copy.c b/window-copy.c
index f5f78cf2..51a8f108 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
diff --git a/window.c b/window.c
index 3b6b74bd..7678adc6 100644
--- a/window.c
+++ b/window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,15 +22,12 @@
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
-#include <paths.h>
#include <pwd.h>
#include <signal.h>
-#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
-#include <util.h>
#include "tmux.h"
@@ -782,6 +779,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
if (tio != NULL)
memcpy(tio2.c_cc, tio->c_cc, sizeof tio2.c_cc);
tio2.c_cc[VERASE] = '\177';
+#ifdef IUTF8
+ if (options_get_number(&wp->window->options, "utf8"))
+ tio2.c_iflag |= IUTF8;
+#endif
if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
fatal("tcgetattr failed");
diff --git a/www/images/tmux3.png b/www/images/tmux3.png
new file mode 100644
index 00000000..689a2833
--- /dev/null
+++ b/www/images/tmux3.png
Binary files differ
diff --git a/www/images/tmux4.png b/www/images/tmux4.png
new file mode 100644
index 00000000..9e3da3f1
--- /dev/null
+++ b/www/images/tmux4.png
Binary files differ
diff --git a/www/images/tmux5.png b/www/images/tmux5.png
new file mode 100644
index 00000000..83cd7e15
--- /dev/null
+++ b/www/images/tmux5.png
Binary files differ
diff --git a/www/index.html.in b/www/index.html.in
new file mode 100644
index 00000000..5e0276e8
--- /dev/null
+++ b/www/index.html.in
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>tmux</title>
+ <link rel="stylesheet" type="text/css" media="screen" href="main.css"/>
+ </head>
+ <body>
+ <div id="body-wrapper">
+ <div id="left-menu-container">
+ <p id="upper-left-title">tmux</p>
+ <ul id="left-menu">
+ <li><a href="http://downloads.sourceforge.net/tmux/tmux-%%VERSION%%.tar.gz">Download</a></li>
+ <li><a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/README">README</a></li>
+ <li><a href="http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1">Manual Page</a></li>
+ <li><a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/FAQ">FAQ</a></li>
+ <li><a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/">Source Code</a></li>
+ <li><a href="http://sf.net/projects/tmux">SourceForge Page</a></li>
+ <li><a href="https://lists.sourceforge.net/lists/listinfo/tmux-users">Mailing List</a></li>
+ <li><a href="irc://irc.freenode.net/tmux">IRC Channel</a></li>
+ </ul>
+ </div>
+ <div id="main-content-wrapper">
+
+<p><b>tmux is a terminal multiplexer</b></p>
+
+<p><b>What is a terminal multiplexer?</b> It lets you switch easily between
+several programs in one terminal, detach them (they keep running in the
+background) and reattach them to a different terminal. And do a lot more. See
+<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=tmux&sektion=1">
+the manual</a>.</p>
+
+<p><b><a href="http://downloads.sourceforge.net/tmux/tmux-%%VERSION%%.tar.gz">
+Download tmux %%VERSION%%</a></b> or
+<a href="https://sourceforge.net/p/tmux/tmux-code/ci/master/tree/">
+get the development version.</a>
+tmux is hosted on
+<a href="http://sf.net/projects/tmux">SourceForge</a>
+and needs
+<a href="http://www.monkey.org/~provos/libevent/">libevent</a>
+and
+<a href="http://invisible-island.net/ncurses/">ncurses</a>
+.</p>
+
+<p>For support contact the
+<a href="mailto:tmux-users@lists.sf.net">tmux-users@lists.sf.net</a>
+mailing list or IRC channel
+<a href="irc://irc.freenode.net/tmux">#tmux on freenode</a>.</p>
+
+<p>There are some programs to use with tmux
+<a href="https://github.com/search?q=tmux&type=Repositories&ref=simplesearch">
+on GitHub</a> and a
+<a href="http://pragprog.com/book/bhtmux/tmux">book on tmux</a>.</p>
+
+<div id="screenshots">
+ <a href="tmux3.png"><img src="small-tmux3.png" alt="Screenshot"/></a>
+ <a href="tmux4.png"><img src="small-tmux4.png" alt="Screenshot"/></a>
+ <a href="tmux5.png"><img src="small-tmux5.png" alt="Screenshot"/></a>
+</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/www/main.css b/www/main.css
new file mode 100644
index 00000000..28b58424
--- /dev/null
+++ b/www/main.css
@@ -0,0 +1,50 @@
+body {
+ font-family: Sans-Serif;
+ font-size: 10pt;
+ background-color: white;
+}
+#body-wrapper {
+ overflow: auto;
+}
+#upper-left-title {
+ font-size:xx-large;
+ margin-top: 0;
+}
+#left-menu li {
+ list-style: none;
+ margin-top: 1em;
+}
+.menu-headings {
+ border-top: 1px solid black;
+ border-bottom: 1px solid black;
+ font-weight: bold;
+ padding: 0.5em;
+}
+#left-menu-container {
+ padding-right: 0.5em;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ margin-right: 0.5em;
+ border-right: 3px solid black;
+ text-align: right;
+ width: 12em;
+ float: left;
+}
+#main-content-wrapper {
+ margin-left: 2em;
+ margin-right: 4em;
+}
+#main-content-wrapper li {
+ list-style: disc;
+ margin-left: 12em
+}
+#screenshots {
+ text-align: center;
+ margin: 1em;
+ margin-left: 10em;
+}
+#screenshots img {
+ text-align: center;
+ margin: 0.5em;
+}
+
diff --git a/xmalloc.c b/xmalloc.c
index cb734edc..df583e55 100644
--- a/xmalloc.c
+++ b/xmalloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2004 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,7 +20,6 @@
#include <errno.h>
#include <libgen.h>
-#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/xterm-keys.c b/xterm-keys.c
index 75eb6751..8c885875 100644
--- a/xterm-keys.c
+++ b/xterm-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $Id$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>