diff options
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 @@ -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 @@ -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 @@ -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> @@ -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" @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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; @@ -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> @@ -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> @@ -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; @@ -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) @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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 @@ -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> @@ -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> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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 { @@ -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" @@ -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()); +} @@ -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" @@ -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> @@ -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> @@ -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]); @@ -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> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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 , @@ -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)); } @@ -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 @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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 @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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> @@ -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 Binary files differnew file mode 100644 index 00000000..689a2833 --- /dev/null +++ b/www/images/tmux3.png diff --git a/www/images/tmux4.png b/www/images/tmux4.png Binary files differnew file mode 100644 index 00000000..9e3da3f1 --- /dev/null +++ b/www/images/tmux4.png diff --git a/www/images/tmux5.png b/www/images/tmux5.png Binary files differnew file mode 100644 index 00000000..83cd7e15 --- /dev/null +++ b/www/images/tmux5.png 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; +} + @@ -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> |