├── MIT-LICENSE ├── README.md ├── man └── wemux.1 ├── wemux └── wemux.conf.example /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt Furden 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | Software), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![wemux: Multi-User Tmux Sessions Made Easy](http://i.imgur.com/iOjcz.png) 2 | ******************************************************************************** 3 | 4 | wemux enhances tmux to make multi-user terminal multiplexing both easier and 5 | more powerful. It allows users to host a wemux server and have clients join 6 | in either: 7 | 8 | **Mirror Mode** gives clients (another SSH user on your machine) read-only 9 | access to the session, allowing them to see you work, or 10 | 11 | **Pair Mode** allows the client and yourself to work in the same terminal 12 | (shared cursor) 13 | 14 | **Rogue Mode** allows the client to pair or work independently in another 15 | window (separate cursors) in the same tmux session. 16 | 17 | It features multi-server support as well as user listing 18 | and notifications when users attach/detach. 19 | 20 | ## How To Install 21 | **IMPORTANT**: Wemux requires tmux version >= 1.6 22 | 23 | ### MacPorts (on OS X) 24 | If you have [MacPorts](https://www.macports.org/) installed you can 25 | install wemux with a very simple: 26 | 27 | sudo port install wemux 28 | 29 | ### Homebrew (on OS X) 30 | If you have [Homebrew](http://mxcl.github.com/homebrew/) installed you can 31 | install wemux with a fairly simple: 32 | 33 | brew install wemux 34 | 35 | The user that installed wemux will automatically be added to the wemux host list. 36 | To change the host or add more hosts, edit `/usr/local/etc/wemux.conf` and add the 37 | username to the host_list array. 38 | 39 | Users in the host_list will be able to start new wemux servers, all other 40 | users will be wemux clients and join these servers. 41 | 42 | $ vim /usr/local/etc/wemux.conf 43 | OR 44 | $ wemux conf 45 | 46 | host_list=(zolrath brocksamson) 47 | 48 | ### Manual Installation 49 | The rest of this readme will operate under the assumption you'll place wemux 50 | in `wemux/` in your `/usr/local/share` directory. To make wemux available for 51 | all users, perform the following steps, using sudo as required: 52 | 53 | Git clone this repo. 54 | 55 | git clone git://github.com/zolrath/wemux.git /usr/local/share/wemux 56 | 57 | Symlink the `wemux` file into your $PATH via `/usr/local/bin/`, 58 | being sure to use the full path. 59 | 60 | ln -s /usr/local/share/wemux/wemux /usr/local/bin/wemux 61 | 62 | **IMPORTANT**: Copy the `wemux.conf.example` file to `/usr/local/etc/wemux.conf` 63 | 64 | cp /usr/local/share/wemux/wemux.conf.example /usr/local/etc/wemux.conf 65 | 66 | Then set a user to be a wemux host by adding their username to the host_list in 67 | `/usr/local/etc/wemux.conf`. Users in the host_list will be able to start new wemux 68 | servers, all other users will be wemux clients and join these servers. 69 | 70 | vim /usr/local/etc/wemux.conf 71 | host_list=(zolrath brocksamson) 72 | 73 | To upgrade to a new version of wemux return to the `/usr/local/share/wemux` 74 | directory and perform a `git pull` 75 | 76 | ## Host Commands 77 | #### wemux start 78 | Use `wemux start` to start a wemux server, chmod /tmp/wemux-wemux to 1777 so 79 | that other users may connect to it, and attach to it. If a wemux server 80 | already exists, it will attach to it instead. 81 | #### wemux attach 82 | Use `wemux attach` to attach to an existing wemux server. 83 | #### wemux stop 84 | Use `wemux stop` to kill the wemux server and remove the /tmp/wemux-wemux 85 | socket. 86 | #### wemux kick *username* 87 | Use `wemux kick ` to kick an SSH user from the server and remove 88 | their wemux rogue sessions. 89 | #### wemux config 90 | Use `wemux config` to open `/usr/local/etc/wemux.conf` in your $EDITOR. 91 | Note this only works if you have the environment variable EDITOR configured. 92 | #### wemux 93 | When `wemux` is run without any arguments in host mode, it is just like 94 | running wemux start. It will reattach to an existing wemux server if it 95 | exists, otherwise it will start a new server. 96 | 97 | ## Client Commands 98 | #### wemux mirror 99 | Use `wemux mirror` to attach to server in read-only mode. 100 | #### wemux pair 101 | Use `wemux pair` to attach to server in pair mode, allowing the client to 102 | control the terminal as well. 103 | #### wemux rogue 104 | Use `wemux rogue` to attach to server in rogue mode, which allows both editing 105 | with the host and switching to windows independently from the host. 106 | #### wemux logout 107 | Use `wemux logout` to remove your rogue mode session. 108 | #### wemux 109 | When `wemux` is run without any arguments in client mode, its behavior 110 | attempts to intelligently select mirror, pair, or rogue: 111 | 112 | * If the client does not have an existing rogue session it will attach to the 113 | wemux server in pair mode. 114 | * If the client has already started a wemux rogue session, it will 115 | reattach to the server in rogue mode. 116 | * If both rogue and pair mode are disabled, it will attach in mirror mode. 117 | * By setting `default_client_mode="rogue"` in `wemux.conf` this can be changed 118 | to always join in rogue mode, even if a rogue session doesn't already exist. 119 | 120 | #### Other Commands 121 | wemux passes commands it doesn't understand through to tmux with the correct 122 | socket setting. 123 | 124 | `wemux list-sessions` is equivalent to entering `tmux -S /tmp/wemux-wemux 125 | list-sessions` 126 | 127 | ## User List 128 | wemux can display a list of connected users, indicating users in mirror mode 129 | with [m] at the end of their name. 130 | 131 | If you'd like to see a list of all users currently connected to the wemux 132 | server, you have three options: 133 | 134 | ### wemux users 135 | Enter `wemux users` in the terminal to display a list of all currently 136 | connected wemux users. 137 | 138 | $ wemux users 139 | Users connected to 'wemux': 140 | 1. zolrath 141 | 2. csagan[m] 142 | 143 | ### Status Bar 144 | You can add the user list to your status bar by adding #(wemux status_users) 145 | where you see fit by editing your `~/tmux.conf` file. 146 | 147 | set -g status-right "#(wemux status_users)" 148 | 149 | ### Display Message 150 | If you'd rather display users on command via a tmux message, similar to the 151 | user attachment/detachment messages, you can do so by editing your 152 | `~/tmux.conf` file. Pick whatever key you'd like to bind the displaying the 153 | message to. Using t as an example: 154 | 155 | unbind t 156 | bind t run-shell 'wemux display_users' 157 | 158 | Note that the tmux prefix should be pressed before t to activate the command. 159 | 160 | User listing can be disabled by setting `allow_user_list="false"` in 161 | `wemux.conf` 162 | 163 | ### Short-form Commands 164 | All commands have a short form. s for start, a for attach, p for pair etc. 165 | For a complete list, type `wemux help` (or `wemux h`) 166 | 167 | # Multi-Host Capabilities 168 | ******************************************************************************** 169 | 170 | wemux supports specifying the joining different wemux servers via `wemux join 171 | `. This allows multiple hosts on the same machine to host their own 172 | independent wemux servers with their own clients. By default this option is 173 | disabled. 174 | 175 | wemux will remember the last server specified to in order to make reconnecting 176 | to the same server easy. `wemux help` will output the currently specified 177 | server along with the wemux command list. 178 | 179 | Changing servers can be enabled by setting `allow_server_change="true"` in 180 | `/usr/local/etc/wemux.conf` 181 | 182 | ### Joining Different wemux Servers 183 | To change the wemux server run `wemux join `. The name will be sanitized to contain no spaces or uppercase letters. 184 | 185 | $ wemux join Project X 186 | Changed wemux server from 'wemux' to 'project-x' 187 | $ wemux 188 | $ wemux stop 189 | $ wemux reset 190 | Changed wemux server from 'project-x' to 'wemux' 191 | 192 | #### wemux join *servername* 193 | Join wemux server with specified name. 194 | 195 | $ wemux join rails 196 | Changed wemux server from 'wemux' to 'rails' 197 | 198 | #### wemux join *servernumber* 199 | Alternatively, enter the server number displayed next to the server name in `wemux list`. 200 | 201 | $ wemux j 1 202 | Changed wemux server from 'rails' to 'project-x' 203 | 204 | #### wemux join 205 | Join with no argument simply displays the current wemux server, if you're into that. 206 | 207 | $ wemux join 208 | Current wemux server: wemux 209 | 210 | ### Resetting the Server Name 211 | In order to easily return to the default server you can run `wemux reset` 212 | #### wemux reset 213 | Joins the default wemux server: wemux (or value of default_server_name in wemux.conf) 214 | 215 | $ wemux reset 216 | Changed wemux server from 'project-x' to 'wemux' 217 | 218 | ### Active Server List 219 | To list the name of all currently running wemux servers run `wemux list` 220 | #### wemux list 221 | List all currently active wemux servers. 222 | 223 | $ wemux list 224 | Currently active wemux servers: 225 | 1. project-x 226 | 2. rails 227 | 3. wemux <- current server 228 | 229 | `wemux join` and `wemux stop` both accept either the name of a server or 230 | the number indicated next to the name in `wemux list`. 231 | 232 | Listing servers can be disabled by setting `allow_server_list="false"` in 233 | `/usr/local/etc/wemux.conf` 234 | 235 | # Configuration 236 | ******************************************************************************** 237 | 238 | There are a number of additional options that be configured in 239 | `/usr/local/etc/wemux.conf`. In most cases the only option that must be changed is the 240 | `host_list` array. To open your wemux configuration file, you can either open 241 | `/usr/local/etc/wemux.conf` manually or run `wemux config` 242 | 243 | ### Host Mode 244 | To have an account act as host, ensure that you have added their username to the 245 | `/usr/local/etc/wemux.conf` file's `host_list` array. 246 | 247 | host_list=(zolrath hostusername brocksamson) 248 | 249 | ### Pair Mode 250 | Pair mode can be disabled, only allowing clients to attach to the server in 251 | mirror mode by setting `allow_pair_mode="false"` 252 | 253 | ### Rogue Mode 254 | Rogue mode can be disabled, only allowing clients to attach to the server in 255 | mirror or pair mode by setting `allow_rogue_mode="false"` 256 | 257 | ### Default Client Mode 258 | When clients enter 'wemux' with no arguments by default it will first attempt to 259 | join an existing rogue mode session. If there is no rogue session it will start 260 | in pair mode. 261 | By setting default_client_mode to "rogue", 'wemux' with no arguments will always 262 | join a rogue mode session, even if it has to create it. 263 | 264 | This can be changed by setting `default_client_mode="rogue"` 265 | 266 | ### Default Server Name 267 | The default wemux server name will be used with `wemux reset` and when 268 | `allow_server_name` is not enabled in `wemux.conf`. 269 | 270 | This can be changed by setting `default_server_name="customname"` 271 | 272 | ### Changing Servers 273 | The ability to change servers can be enabled by setting 274 | `allow_server_change="true"` 275 | 276 | ### Listing Servers 277 | Listing servers can be disabled by setting `allow_server_list="false"` 278 | 279 | ### Listing Users 280 | Listing users can be disabled by setting `allow_user_list="false"` in 281 | `wemux.conf` 282 | 283 | ### Kicking SSH Users 284 | Kicking SSH users from the server can be disabled by setting 285 | `allow_kick_user="false"` in `wemux.conf` 286 | 287 | ### Announcements 288 | When a user joins a server in either mirror, pair, or rogue mode, a message is 289 | displayed to all currently attached users: 290 | 291 | csagan has attached in mirror mode. 292 | csagan has detached. 293 | 294 | This can be disabled by setting `announce_attach="false"` 295 | 296 | In addition, when a user switches from one server to another via the `wemux 297 | join ` command, their movement is displayed similarly to the 298 | attach messages. 299 | 300 | If csagan enters `wemux join applepie` the users on the default server 301 | `wemux` will see: 302 | 303 | csagan has switched to server: applepie 304 | 305 | If csagan returns to default server with: `wemux reset` users on `wemux` 306 | will see: 307 | 308 | csagan has joined this server. 309 | 310 | This can be disabled by setting `announce_server_change="false"` 311 | 312 | ### Automatic SSH Client Modes 313 | To make an SSHed user start in a wemux mode automatically, add one of the 314 | following lines to the users `.bash_profile` or `.zshrc` 315 | 316 | **Option 1**: Automatically log the client into mirror mode upon login, 317 | disconnect them from the server when they detach. 318 | 319 | wemux mirror; exit 320 | 321 | **Option 2**: Automatically start the client in mirror mode but allow them to 322 | detach. 323 | 324 | wemux mirror 325 | 326 | **Option 3**: Automatically start the client in pair mode but allow them to 327 | detach. 328 | 329 | wemux pair 330 | 331 | **Option 4**: Automatically start the client in rogue mode but allow them to 332 | detach. 333 | 334 | wemux rogue 335 | 336 | **Option 5**: Only display the connection commands, don't automatically start 337 | any modes. 338 | 339 | wemux help 340 | 341 | Please note that this does not ensure a logged in user will not be able to exit 342 | tmux and access their shell. If the user is not trusted, you must perform any 343 | security measures one would normally perform for a remote user. 344 | -------------------------------------------------------------------------------- /man/wemux.1: -------------------------------------------------------------------------------- 1 | .\" generated with Ronn/v0.7.3 2 | .\" http://github.com/rtomayko/ronn/tree/0.7.3 3 | . 4 | .TH "WEMUX" "1" "March 2014" "" "" 5 | . 6 | .SH "NAME" 7 | \fBwemux\fR \- multi\-user tmux sessions made easy 8 | . 9 | .SH "SYNOPSIS" 10 | Host or join multi\-user tmux sessions\. 11 | . 12 | .P 13 | WEMUX HOST COMMANDS 14 | . 15 | .br 16 | \fBwemux start\fR 17 | . 18 | .br 19 | \fBwemux attach\fR 20 | . 21 | .br 22 | \fBwemux stop\fR 23 | . 24 | .br 25 | \fBwemux users\fR 26 | . 27 | .br 28 | \fBwemux kick\fR 29 | . 30 | .br 31 | \fBwemux config\fR 32 | . 33 | .br 34 | \fBwemux help\fR 35 | . 36 | .br 37 | WEMUX CLIENT COMMANDS: 38 | . 39 | .br 40 | \fBwemux mirror\fR 41 | . 42 | .br 43 | \fBwemux pair\fR 44 | . 45 | .br 46 | \fBwemux rogue\fR 47 | . 48 | .br 49 | \fBwemux logout\fR 50 | . 51 | .br 52 | WEMUX SESSION COMMANDS: 53 | . 54 | .br 55 | \fBwemux join\fR 56 | . 57 | .br 58 | \fBwemux reset\fR 59 | . 60 | .br 61 | \fBwemux list\fR 62 | . 63 | .br 64 | . 65 | .SH "DESCRIPTION" 66 | wemux enhances tmux to make multi\-user terminal multiplexing both easier and more powerful\. It allows users to host a wemux session and have clients join in either: 67 | . 68 | .P 69 | \fBMirror Mode\fR gives clients (another SSH user on your machine) read\-only access to the session, allowing them to see you work, or 70 | . 71 | .P 72 | \fBPair Mode\fR allows the client and yourself to work in the same terminal (shared cursor) or work independently in another window (separate cursors) in the same tmux session\. 73 | . 74 | .P 75 | It features multi\-session support as well as user listing and notifications when users attach/detach\. 76 | . 77 | .SH "HOST COMMANDS" 78 | . 79 | .SS "wemux start" 80 | Start a wemux session, chmod /tmp/wemux\-wemux to 1777 so that other users may connect to it, and attach to it\. If a wemux session already exists, it will attach to it instead\. 81 | . 82 | .SS "wemux attach" 83 | Attach to an existing wemux session\. 84 | . 85 | .SS "wemux stop" 86 | Kill the wemux session and remove the /tmp/wemux\-wemux socket\. 87 | . 88 | .SS "wemux kick username" 89 | Kick an SSH user from the server and remove their wemux pair sessions\. 90 | . 91 | .SS "wemux config" 92 | Open \fB/usr/local/etc/wemux\.conf\fR in your $EDITOR\. 93 | . 94 | .SS "wemux" 95 | When \fBwemux\fR is run without any arguments in host mode, it is just like running wemux start\. It will reattach to an existing wemux session if it exists, otherwise it will start a new session\. 96 | . 97 | .SH "CLIENT COMMANDS" 98 | . 99 | .SS "wemux mirror" 100 | Attach to session in read\-only mode\. 101 | . 102 | .SS "wemux pair" 103 | Attach to session in pair mode, which allows editing\. 104 | . 105 | .SS "wemux rogue" 106 | Attach to server in rogue mode, which allows editing and switching to windows independently from the host\. 107 | . 108 | .SS "wemux logout" 109 | Remove your pair mode session\. 110 | . 111 | .SS "wemux" 112 | When \fBwemux\fR is run without any arguments in client mode, its behavior attempts to intelligently select mirror, pair or rogue: 113 | . 114 | .IP "\(bu" 4 115 | If the client does not have an existing rogue session it will attach to the wemux session in pair mode\. 116 | . 117 | .IP "\(bu" 4 118 | If the client has already started a wemux rogue mode session, it will reattach to the session in rogue mode\. 119 | . 120 | .IP "\(bu" 4 121 | By setting \fBdefault_client_mode="rogue"\fR in \fBwemux\.conf\fR this can be changed to always join in pair mode, even if a pair session doesn\'t already exist\. 122 | . 123 | .IP "" 0 124 | . 125 | .SS "Other Commands" 126 | wemux passes commands it doesn\'t understand through to tmux with the correct socket setting\. 127 | . 128 | .P 129 | \fBwemux list\-sessions\fR is equivalent to entering \fBtmux \-S /tmp/wemux\-wemux list\-sessions\fR 130 | . 131 | .SH "USER LIST" 132 | wemux can display a list of connected users, indicating users in mirror mode with [m] at the end of their name\. 133 | . 134 | .P 135 | If you\'d like to see a list of all users currently connected to the wemux session, you have three options: 136 | . 137 | .SS "wemux users" 138 | Enter \fBwemux users\fR in the terminal to display a list of all currently connected wemux users\. 139 | . 140 | .IP "" 4 141 | . 142 | .nf 143 | 144 | $ wemux users 145 | Users connected to \'wemux\': 146 | 1\. zolrath 147 | 2\. csagan[m] 148 | . 149 | .fi 150 | . 151 | .IP "" 0 152 | . 153 | .SS "Status Bar" 154 | You can add the user list to your status bar by adding #(wemux status_users) where you see fit by editing your \fB~/tmux\.conf\fR file\. 155 | . 156 | .IP "" 4 157 | . 158 | .nf 159 | 160 | set \-g status\-right "#(wemux status_users)" 161 | . 162 | .fi 163 | . 164 | .IP "" 0 165 | . 166 | .SS "Display Message" 167 | If you\'d rather display users on command via a tmux message, similar to the user attachment/detachment messages, you can do so by editing your \fB~/tmux\.conf\fR file\. Pick whatever key you\'d like to bind the displaying the message to\. Using t as an example: 168 | . 169 | .IP "" 4 170 | . 171 | .nf 172 | 173 | unbind t 174 | bind t run\-shell \'wemux display_users\' 175 | . 176 | .fi 177 | . 178 | .IP "" 0 179 | . 180 | .P 181 | Note that the tmux prefix should be pressed before t to activate the command\. 182 | . 183 | .P 184 | User listing can be disabled by setting \fBallow_user_list="false"\fR in \fBwemux\.conf\fR 185 | . 186 | .SS "Short\-form Commands" 187 | All commands have a short form\. s for start, a for attach, p for pair etc\. For a complete list, type \fBwemux help\fR (or \fBwemux h\fR) 188 | . 189 | .SH "MULTI\-HOST MODE" 190 | wemux supports specifying the joining different wemux sessions via \fBwemux join \fR\. This allows multiple hosts on the same machine to host their own independent wemux sessions with their own clients\. By default this option is disabled\. 191 | . 192 | .P 193 | wemux will remember the last session specified to in order to make reconnecting to the same session easy\. \fBwemux help\fR will output the currently specified session along with the wemux command list\. 194 | . 195 | .P 196 | Changing sessions can be enabled by setting \fBallow_session_change="true"\fR in \fB/usr/local/etc/wemux\.conf\fR 197 | . 198 | .SS "Joining Different wemux Sessions" 199 | To change the wemux session run \fBwemux join \fR\. The name will be sanitized to contain no spaces or uppercase letters\. 200 | . 201 | .IP "" 4 202 | . 203 | .nf 204 | 205 | $ wemux join Project X 206 | Changed wemux session from \'wemux\' to \'project\-x\' 207 | $ wemux start 208 | $ wemux 209 | $ wemux stop 210 | $ wemux reset 211 | Changed wemux session from \'project\-x\' to \'wemux\' 212 | . 213 | .fi 214 | . 215 | .IP "" 0 216 | . 217 | .SS "wemux join sessionname" 218 | Join wemux session with specified name\. 219 | . 220 | .IP "" 4 221 | . 222 | .nf 223 | 224 | $ wemux join rails 225 | Changed wemux session from \'wemux\' to \'rails\' 226 | . 227 | .fi 228 | . 229 | .IP "" 0 230 | . 231 | .SS "wemux join sessionnumber" 232 | Alternatively, enter the session number displayed next to the session name in \fBwemux list\fR\. 233 | . 234 | .IP "" 4 235 | . 236 | .nf 237 | 238 | $ wemux j 1 239 | Changed wemux session from \'rails\' to \'project\-x\' 240 | . 241 | .fi 242 | . 243 | .IP "" 0 244 | . 245 | .SS "wemux join" 246 | Join with no argument simply displays the current wemux server, if you\'re into that\. 247 | . 248 | .IP "" 4 249 | . 250 | .nf 251 | 252 | $ wemux join 253 | Current wemux server: wemux 254 | . 255 | .fi 256 | . 257 | .IP "" 0 258 | . 259 | .SS "Resetting the Session Name" 260 | In order to easily return to the default session you can run \fBwemux reset\fR 261 | . 262 | .SS "wemux reset" 263 | Joins the default wemux session: wemux (or value of default_session_name in wemux\.conf) 264 | . 265 | .IP "" 4 266 | . 267 | .nf 268 | 269 | $ wemux reset 270 | Changed wemux session from \'project\-x\' to \'wemux\' 271 | . 272 | .fi 273 | . 274 | .IP "" 0 275 | . 276 | .SS "Active Session List" 277 | To list the name of all currently running wemux sessions run \fBwemux list\fR 278 | . 279 | .SS "wemux list" 280 | List all currently active wemux sessions\. 281 | . 282 | .IP "" 4 283 | . 284 | .nf 285 | 286 | $ wemux list 287 | Currently active wemux sessions: 288 | 1\. project\-x 289 | 2\. rails 290 | 3\. wemux <\- current session 291 | . 292 | .fi 293 | . 294 | .IP "" 0 295 | . 296 | .P 297 | \fBwemux join\fR and \fBwemux stop\fR both accept either the name of a session or the number indicated next to the name in \fBwemux list\fR\. 298 | . 299 | .P 300 | Listing sessions can be disabled by setting \fBallow_session_list="false"\fR in \fB/usr/local/etc/wemux\.conf\fR 301 | . 302 | .SH "CONFIGURATION" 303 | There are a number of additional options that be configured in \fB/usr/local/etc/wemux\.conf\fR\. In most cases the only option that must be changed is the \fBhost_list\fR array\. To open your wemux configuration file, you can either open \fB/usr/local/etc/wemux\.conf\fR manually or run \fBwemux config\fR 304 | . 305 | .SS "Host Mode" 306 | To have an account act as host, ensure that you have added their username to the \fB/usr/local/etc/wemux\.conf\fR file\'s \fBhost_list\fR array\. 307 | . 308 | .IP "" 4 309 | . 310 | .nf 311 | 312 | host_list=(zolrath hostusername brocksamson) 313 | . 314 | .fi 315 | . 316 | .IP "" 0 317 | . 318 | .SS "Pair Mode" 319 | Pair mode can be disabled, only allowing clients to attach to the session in mirror mode by setting \fBallow_pair_mode="false"\fR 320 | . 321 | .SS "Rogue Mode" 322 | Rogue mode can be disabled, only allowing clients to attach to the server in mirror or pair mode by setting \fBallow_rogue_mode="false"\fR 323 | . 324 | .SS "Default Client Mode" 325 | When clients enter \'wemux\' with no arguments by default it will first attempt to join an existing rogue mode session\. If there is no rogue session it will start in pair mode\. By setting default_client_mode to "rogue", \'wemux\' with no arguments will always join a rogue mode session, even if it has to create it\. 326 | . 327 | .P 328 | This can be changed by setting \fBdefault_client_mode="rogue"\fR 329 | . 330 | .SS "Default Session Name" 331 | The default wemux session name will be used with \fBwemux reset\fR and when \fBallow_session_change\fR is not enabled in \fBwemux\.conf\fR\. 332 | . 333 | .P 334 | This can be changed by setting \fBdefault_session_name="customname"\fR 335 | . 336 | .SS "Changing Sessions" 337 | The ability to change sessions can be enabled by setting \fBallow_session_change="true"\fR 338 | . 339 | .SS "Listing Sessions" 340 | Listing sessions can be disabled by setting \fBallow_session_list="false"\fR 341 | . 342 | .SS "Listing Users" 343 | Listing users can be disabled by setting \fBallow_user_list="false"\fR in \fBwemux\.conf\fR 344 | . 345 | .SS "Kicking SSH Users" 346 | Kicking SSH users from the server can be disabled by setting \fBallow_kick_user="false"\fR in \fBwemux\.conf\fR 347 | . 348 | .SS "Announcements" 349 | When a user joins a session in either mirror or pair mode, a message is displayed to all currently attached users: 350 | . 351 | .IP "" 4 352 | . 353 | .nf 354 | 355 | csagan has attached in mirror mode\. 356 | csagan has detached\. 357 | . 358 | .fi 359 | . 360 | .IP "" 0 361 | . 362 | .P 363 | This can be disabled by setting \fBannounce_attach="false"\fR 364 | . 365 | .P 366 | In addition, when a user switches from one session to another via the \fBwemux join \fR command, their movement is displayed similarly to the attach messages\. 367 | . 368 | .P 369 | If csagan enters \fBwemux join applepie\fR the users on the default session \fBwemux\fR will see: 370 | . 371 | .IP "" 4 372 | . 373 | .nf 374 | 375 | csagan has switched to session: applepie 376 | . 377 | .fi 378 | . 379 | .IP "" 0 380 | . 381 | .P 382 | If csagan returns to default session with: \fBwemux reset\fR users on \fBwemux\fR will see: 383 | . 384 | .IP "" 4 385 | . 386 | .nf 387 | 388 | csagan has joined this session\. 389 | . 390 | .fi 391 | . 392 | .IP "" 0 393 | . 394 | .P 395 | This can be disabled by setting \fBannounce_session_change="false"\fR 396 | . 397 | .SS "Automatic SSH Client Modes" 398 | To make an SSHed user start in a wemux mode automatically, add one of the following lines to the users \fB\.bash_profile\fR or \fB\.zshrc\fR 399 | . 400 | .P 401 | \fBOption 1\fR: Automatically log the client into mirror mode upon login, disconnect them from the server when they detach\. \fBwemux mirror; exit\fR 402 | . 403 | .br 404 | . 405 | .P 406 | \fBOption 2\fR: Automatically start the client in mirror mode but allow them to detach\. 407 | . 408 | .br 409 | \fBwemux mirror\fR 410 | . 411 | .br 412 | . 413 | .P 414 | \fBOption 3\fR: Automatically start the client in pair mode but allow them to detach\. 415 | . 416 | .br 417 | \fBwemux pair\fR 418 | . 419 | .br 420 | . 421 | .P 422 | \fBOption 4\fR: Only display the connection commands, don\'t automatically start any modes\. 423 | . 424 | .br 425 | \fBwemux help\fR 426 | . 427 | .br 428 | . 429 | .P 430 | Please note that this does not ensure a logged in user will not be able to exit tmux and access their shell\. If the user is not trusted, you must perform any security measures one would normally perform for a remote user\. 431 | -------------------------------------------------------------------------------- /wemux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # wemux by Matt Furden @zolrath 3 | # 4 | # wemux allows you to start a shared tmux session using the command 'wemux'. 5 | # Clients have the option of: 6 | # Mirroring, which will give them read-only access, 7 | # Pairing, which will allow them to control the hosts cursor. 8 | # Rogue mode, which allows them to work in the same window (shared cursor) or 9 | # in another window (separate cursors) in the hosts tmux session. 10 | # 11 | # To set a user as host add their username to the host_list in the configuration 12 | # file located at /usr/local/etc/wemux.conf 13 | # Other configuations options are also located in /usr/local/etc/wemux.conf 14 | # 15 | # For environments with multiple hosts running their own independent servers 16 | # on the same machine wemux can join different servers with the wemux join 17 | # command, if enabled. This can be enabled in the configuration file. 18 | # 19 | # WEMUX HOST COMMANDS: 20 | # wemux start : Start the wemux server/join an existing wemux server. 21 | # wemux attach: Join an existing wemux server. 22 | # wemux stop : Stop the wemux server. 23 | # wemux users : List the currently attached wemux users. 24 | # wemux kick : Disconnect an SSH user, remove their wemux server. 25 | # wemux config: Open the wemux configuration file in your $EDITOR. 26 | # wemux help : Display the help screen. 27 | # 28 | # WEMUX CLIENT COMMANDS: 29 | # wemux mirror: Attach to Host in read-only mode. 30 | # wemux pair : Attach to Host in pair mode, which allows editing. 31 | # wemux rogue : Attach to Host in rogue mode, which allows editing and switching 32 | # to windows independently from the host. 33 | # wemux logout: Log out of the wemux rogueing session. 34 | # wemux users : List the currently attached wemux users. 35 | # wemux help : Display the help screen. 36 | # 37 | # To enable multi-host commands, set allow_server_change="true" in wemux.conf 38 | # WEMUX SESSION COMMANDS: can be run by either host or client. 39 | # wemux join : Join wemux server with supplied name. 40 | # wemux reset : Join default wemux server: wemux 41 | # wemux list : List all currently active wemux servers. 42 | 43 | ############################################################################### 44 | 45 | # Current wemux version. 46 | version="3.2.0" 47 | 48 | # Setup and Configuration Files. 49 | # Default settings, modify them in the /usr/local/etc/wemux.conf file: 50 | host_list=(change_this_in_wemux_conf) 51 | host_groups=() 52 | socket_prefix="/tmp/wemux" 53 | options="-u" 54 | allow_pair_mode="true" 55 | allow_rogue_mode="true" 56 | default_client_mode="mirror" 57 | allow_kick_user="true" 58 | allow_server_change="false" 59 | default_server_name="wemux" 60 | allow_server_list="true" 61 | allow_user_list="true" 62 | announce_attach="true" 63 | announce_server_change="true" 64 | 65 | # Prevent users from changing their $USER env variable to become host. 66 | username=`whoami` 67 | # Set $EDITOR default to vi if not configured on host machine. 68 | editor=${EDITOR:="vi"} 69 | 70 | # Load configuration options from /usr/local/etc/wemux.conf 71 | [ -f /usr/local/etc/wemux.conf ] && . /usr/local/etc/wemux.conf 72 | 73 | # Sanitize server name, replace spaces and underscores with dashes. 74 | # Remove all non alpha-numeric characters, convert to lowercase. 75 | sanitize_server_name() { 76 | local new_server=$@ 77 | local new_server=${new_server// /\-} 78 | local new_server=${new_server//_/\-} 79 | local new_server=${new_server//[^a-zA-Z0-9\-]/} 80 | local new_server=`echo "$new_server" | tr '[A-Z]' '[a-z]'` 81 | echo "$new_server" 82 | } 83 | 84 | # Load the server name of last wemux server. If empty, set to 'wemux'. 85 | # Ensure server name is 'wemux' if allow_server_change is disabled. 86 | # If default_server_name is set in wemux.conf it will be used instead of 'wemux' 87 | load_server_name() { 88 | if [ "$allow_server_change" == "true" ]; then 89 | if [ -f ~/.wemux_last_server ]; then 90 | unclean_server=`cat ~/.wemux_last_server` 91 | # Sanitize loaded server name. 92 | server=`sanitize_server_name $unclean_server` 93 | if ! [[ $unclean_server == $server ]]; then 94 | echo "$server" > ~/.wemux_last_server 95 | fi 96 | else 97 | # If ~/.wemux_last_server doesn't exist set to default_server_name 98 | server="$default_server_name" 99 | fi 100 | else 101 | # If allow_server_change is disabled, set to default_server_name 102 | server="$default_server_name" 103 | fi 104 | } 105 | 106 | # Build $wemux variable to call proper tmux server. 107 | build_wemux_prefix() { 108 | load_server_name 109 | # Set client's rogue mode session name. 110 | client_session="$server-$username" 111 | # Set socket to include server name. 112 | socket="${socket_prefix}-$server" 113 | # Set $wemux to wemux server socket. 114 | wemux="tmux -S $socket $options" 115 | } 116 | 117 | # List all currently running wemux servers. 118 | list_active_servers() { 119 | if [ "$allow_server_change" == "true" ]; then 120 | if [ "$allow_server_list" == "true" ]; then 121 | wemux_server_sockets=$socket_prefix* 122 | for wemux_server in $wemux_server_sockets; do 123 | redirect=`tmux -S $wemux_server server-info 2>&1`; server_running=$? 124 | # Number each active server, give it its own line. 125 | if [ "$server_running" == 0 ]; then 126 | num=$[num+1] 127 | server_name=`echo "$wemux_server" | sed -e "s,$socket_prefix-,,"` 128 | # Add indicator for current wemux server. 129 | if [ "$server_name" == "$server" ]; then 130 | server_name="$server_name <- current server" 131 | fi 132 | server_list="$server_list $num. $server_name\n" 133 | fi 134 | done 135 | if [ -z "$server_list" ]; then 136 | echo "No wemux servers currently active." 137 | else 138 | echo "Currently active wemux servers:" 139 | # Remove last newline 140 | echo -e "${server_list%??}" 141 | fi 142 | # allow_server_list is disabled: 143 | else 144 | echo "Server listing has been disabled." 145 | return 126 146 | fi 147 | # allow_server_change is disabled: 148 | else 149 | echo "Server related commands have been disabled." 150 | return 126 151 | fi 152 | } 153 | 154 | # List users currently attached to wemux server. Username[m] for mirror mode. 155 | # Only contains names. Formatted for being included as part of status bar. 156 | status_users() { 157 | if [ "$allow_user_list" == "true" ]; then 158 | while IFS= read line; do 159 | read tty mode <<<$(echo $line) 160 | # Get user associated with tty 161 | name=`stat -f%Su $tty 2>/dev/null` || name=`stat -c%U $tty 2>/dev/null` 162 | # If user is attached in read-only mode, set mode to [m] 163 | [[ $mode == "(ro)" ]] && mode="[m]" || mode="" 164 | # If user/mode is already is userlist, do not add them again. 165 | if ! [[ "$users" =~ "$name$mode," ]]; then 166 | users="$users$name$mode, " 167 | fi 168 | done < <(wemux list-clients | cut -f1,6 -d ' ' | sed s/://) 169 | # Strip last two characters ', ' 170 | echo "${users%??}" 171 | else 172 | echo "User list disabled." 173 | return 126 174 | fi 175 | } 176 | 177 | list_all_users() { 178 | if [ "$allow_user_list" == "true" ]; then 179 | wemux_server_sockets=$socket_prefix* 180 | for wemux_server in $wemux_server_sockets; do 181 | server_running=`tmux -S $wemux_server list-clients` 182 | if [[ "$server_running" ]] && [[ "$server_running" != *"failed to connect"* ]]; then 183 | server_name=`echo "$wemux_server" | sed -e "s,$socket_prefix-,,"` 184 | echo "Users connected to '$server_name':" 185 | # Get list of users with status_users function. 186 | while IFS= read line; do 187 | read tty mode <<<$(echo $line) 188 | # Get user associated with tty 189 | name=`stat -f%Su $tty 2>/dev/null` || name=`stat -c%U $tty 2>/dev/null` 190 | # If user is attached in read-only mode, set mode to [m] 191 | [[ $mode == "(ro)" ]] && mode="[m]" || mode="" 192 | # If user/mode is already is userlist, do not add them again. 193 | user="$name$mode" 194 | num=$[num+1] 195 | echo " $num. $user" 196 | done < <(tmux -S $wemux_server list-clients -F '#{client_tty}') 197 | fi 198 | done 199 | else 200 | echo "User listing has been disabled." 201 | fi 202 | } 203 | 204 | # List users currently attached to wemux server with informative string. 205 | # More verbose, intended for use in terminal. 206 | list_users() { 207 | if [ "$allow_user_list" == "true" ]; then 208 | redirect=`wemux server-info 2>&1`; server_running=$? 209 | if [ "$server_running" == 0 ]; then 210 | # Get list of users with status_users function. 211 | users="$(wemux status_users)" 212 | # Number each user, give it its own line. 213 | for user in $users; do 214 | num=$[num+1] 215 | user=`echo "$user" | sed -e "s/,//"` 216 | user_list="$user_list $num. $user\n" 217 | done 218 | if [ -z "$user_list" ]; then 219 | echo "No wemux users attached to '$server'." 220 | else 221 | echo "Users attached to '$server': " 222 | # Remove last newline. 223 | echo -e "${user_list%??}" 224 | fi 225 | else 226 | echo "No wemux server running on '$server'. No server, no users!" 227 | fi 228 | else 229 | echo "User listing has been disabled." 230 | fi 231 | } 232 | 233 | # Display the currently attached users verbosely in a tmux message. 234 | display_users() { 235 | redirect=`$wemux display-message "$(wemux users)" 2>&1` 236 | } 237 | 238 | # Returns the host's tty and server name. 239 | get_host_session() { 240 | redirect=`wemux server-info 2>&1`; server_running=$? 241 | if [ "$server_running" == 0 ]; then 242 | while read line; do 243 | read tty current_session <<<$(echo $line) 244 | # Get user associated with tty 245 | name=`stat -f%Su $tty 2>/dev/null` || name=`stat -c%U $tty 2>/dev/null` 246 | if [[ $name == $username ]]; then 247 | host=$tty 248 | host_session=$current_session 249 | fi 250 | done < <(wemux list-clients -F '#{client_tty}') 251 | echo "$host $host_session" 252 | fi 253 | } 254 | 255 | # Toggles mirrored users to pair mode, pair mode to mirrored. 256 | mirror_toggle() { 257 | get_host_session > read host host_session 258 | while read tty; do 259 | if ! [[ $tty == $host ]]; then 260 | redirect=`$wemux switch-client -c $tty -t $host_session -r 2>&1` 261 | fi 262 | done < <(wemux list-clients -F '#{client_tty}') 263 | } 264 | 265 | # Set all users to mirror mode on the hosts current session 266 | mirror_all_users() { 267 | get_host_session > read host host_session 268 | while read line; do 269 | read tty mode <<<$(echo $line) 270 | if ! [[ $tty == $host ]] && [[ $mode == "(ro)" ]]; then 271 | redirect=`$wemux switch-client -c $tty -t $host_session 2>&1` 272 | elif ! [[ $tty == $host ]]; then 273 | redirect=`$wemux switch-client -c $tty -t $host_session -r 2>&1` 274 | fi 275 | done < <(wemux list-clients -F '#{client_tty}') 276 | } 277 | 278 | # Make all users join the hosts session. 279 | summon_all_users() { 280 | get_host_session > read host host_session 281 | while read tty; do 282 | if ! [[ $tty == $host ]]; then 283 | $wemux switch-client -c $tty -t $host_session 284 | fi 285 | done < <(wemux list-clients -F '#{client_tty}') 286 | } 287 | 288 | # Make all mirrored users join the hosts session. 289 | summon_mirrored() { 290 | get_host_session > read host host_session 291 | while read line; do 292 | read tty mode <<<$(echo $line) 293 | if ! [[ $tty == $host ]] && [[ $mode == "(ro)" ]]; then 294 | $wemux switch-client -c $tty -t $host_session 295 | fi 296 | done < <(wemux list-clients -F '#{client_tty}') 297 | } 298 | 299 | # The ugly group of redirects below solve the issue where tmux/epoll causes tmux 300 | # to hang when stderr is redirected to /dev/null in a backwards compatible way. 301 | 302 | # Returns true if host currently has a running wemux session. 303 | session_exists() { 304 | redirect=`$wemux has-session -t $server 2>&1`; does_exist=$? 305 | [ "$does_exist" == 0 ] && return 0 || return 1; 306 | } 307 | 308 | # Returns true if rogue session with current host already exists. 309 | has_rogue_session() { 310 | redirect=`$wemux has-session -t $client_session 2>&1`; does_exist=$? 311 | [ "$does_exist" == 0 ] && return 0 || return 1; 312 | } 313 | 314 | # Returns true if server is successfully killed. 315 | kill_server_successful() { 316 | redirect=`tmux -S $socket kill-server 2>&1`; killed_successfully=$? 317 | [ "$killed_successfully" == 0 ] && return 0 || return 1; 318 | } 319 | 320 | # Announce when user attaches/detaches from server. 321 | # Can be disabled by changing announce_attach to false in /usr/local/etc/wemux.conf 322 | # The first argument specifies the mode the user is attaching in for the message 323 | # All additional arguments get wrapped in the attach/detach messages. 324 | announce_connection() { 325 | connection_type=$1; shift; attach_commands="$@" 326 | [ "$announce_attach" == "true" ] && redirect=`$wemux display-message \ 327 | "$username has attached in $connection_type mode." 2>&1` 328 | $attach_commands 329 | status=$? 330 | [ "$announce_attach" == "true" ] && redirect=`$wemux display-message \ 331 | "$username has detached." 2>&1` 332 | return $status 333 | } 334 | 335 | # Announces when a user joins/changes their server. 336 | # Can be disabled by changing announce_server_change to false in /usr/local/etc/wemux.conf 337 | # Change server name for server, or display server name if no argument is given. 338 | change_server() { 339 | if [ "$allow_server_change" == "true" ]; then 340 | # Sanitize input. 341 | new_server=`sanitize_server_name $@` 342 | old_server=$server 343 | 344 | # Get list of currently running servers 345 | server_names=(`echo $socket_prefix* | sed -e "s,$socket_prefix-,,g"`) 346 | # If user joins a number, go to the server with that number in `wemux list` 347 | [[ "$new_server" =~ ^[0-9]+$ ]] && new_server=${server_names[$new_server-1]} 348 | 349 | if [ -z "$new_server" ]; then 350 | echo "Current wemux server: $server" 351 | elif [ "$new_server" == "$old_server" ]; then 352 | echo "Your wemux server is already set to '$server'" 353 | else 354 | # Announce that the user has changed servers to current server. 355 | [ "$announce_server_change" == "true" ] && redirect=`$wemux display-message \ 356 | "$username has switched to server: $new_server" 2>&1` 357 | echo "Changed wemux server from '$old_server' to '$new_server'" 358 | echo $new_server > ~/.wemux_last_server 359 | # Rebuild wemux prefix for new server name. 360 | build_wemux_prefix 361 | # Announce that the user has joined to new server. 362 | [ "$announce_server_change" == "true" ] && redirect=`$wemux display-message \ 363 | "$username has joined this server" 2>&1` 364 | fi 365 | else 366 | echo "Changing wemux servers has been disabled." 367 | return 126 368 | fi 369 | return 0 370 | } 371 | 372 | # Display version of wemux installed on system. Show URL for wemux. 373 | display_version() { 374 | echo "wemux $version" 375 | echo "To check for a newer version visit: http://www.github.com/zolrath/wemux" 376 | } 377 | 378 | # Host mode, used when user is listed in the host_list array in /usr/local/etc/wemux.conf 379 | host_mode() { 380 | # Start the server if it doesn't exist, otherwise reattach. 381 | start_server() { 382 | if ! session_exists; then 383 | $wemux new-session -d -s $server 384 | # Open tmux socket to all users to allow clients to connect. 385 | chmod 1777 $socket 386 | echo "wemux server started on '$server'." 387 | fi 388 | reattach 389 | } 390 | 391 | # Reattach to the wemux server. 392 | reattach() { 393 | if session_exists; then 394 | $wemux attach -t $server 395 | else 396 | echo "No wemux server to attach to on '$server'." 397 | fi 398 | } 399 | 400 | # Kick an SSH user off the server and remove their rogue session if it exists. 401 | kick_user() { 402 | if [ "$allow_kick_user" == "true" ]; then 403 | kicked_user=$1 404 | echo "Kicking $kicked_user from the server. Sudo required." 405 | # Get sshd process with users name and get its PID. 406 | user_pid=`sudo lsof -t -u $kicked_user -c sshd -a` 407 | # Kill the sshd process of the supplied user. 408 | redirect=`sudo kill -9 $user_pid 2>&1`; kicked_successfully=$? 409 | # Remove any tmux sessions ending in "-kicked_user" 410 | `wemux kill-session -t "*-$kicked_user" > /dev/null 2>&1` 411 | if [ "$kicked_successfully" == 0 ]; then 412 | echo "$kicked_user kicked successfully!" 413 | else 414 | echo "$kicked_user was not kicked. Are you sure they're connected?" 415 | fi 416 | else 417 | echo "Kicking users has been disabled." 418 | fi 419 | } 420 | 421 | # Stop the wemux session and remove the socket file. 422 | stop_server() { 423 | server_sockets=(`echo $socket_prefix*`) 424 | # If a specific server is supplied: 425 | if [ $1 ]; then 426 | # If user enters a number, stop the server with that number in `wemux list` 427 | if [[ $@ =~ ^[0-9]+$ ]]; then 428 | socket=${server_sockets[$1-1]} 429 | server=`echo $socket | sed -e "s,$socket_prefix-,,g"` 430 | # Otherwise, stop the server with the supplied name. 431 | else 432 | server=`sanitize_server_name $@` 433 | socket="$socket_prefix-$server" 434 | fi 435 | fi 436 | # If the user doesn't pass an argument, stop current server. 437 | if kill_server_successful; then 438 | echo "wemux server on '$server' stopped." 439 | else 440 | echo "No wemux server running on '$server'" 441 | fi 442 | # If the socket file exists: 443 | if [ -e "$socket" ]; then 444 | if ! rm $socket; then 445 | echo "Could not remove '$socket'. Please check file ownership." 446 | fi 447 | fi 448 | } 449 | 450 | # Display the commands available in host mode. 451 | display_host_commands() { 452 | echo "wemux version $version" 453 | if [ "$allow_server_change" == "true" ]; then 454 | echo "Current wemux server: $server" 455 | fi 456 | echo "" 457 | echo "Usage: wemux [command]" 458 | echo "To host a wemux server please use one of the following:" 459 | echo "" 460 | echo " [s] start: Start the wemux server/attach to an existing wemux server." 461 | echo " [a] attach: Attach to an existing wemux server." 462 | echo " [k] stop: Kill the wemux server '$server', delete its socket." 463 | echo "" 464 | if [ "$allow_server_change" == "true" ]; then 465 | echo " [j] join [name]: Join the specified wemux server." 466 | echo " [j] join: Display the current wemux server." 467 | echo " [d] reset: Join default wemux server: $default_server_name" 468 | if [ "$allow_server_list" == "true" ]; then 469 | echo " [l] list: List all currently active wemux servers." 470 | fi 471 | fi 472 | if [ "$allow_user_list" == "true" ]; then 473 | echo " [u] users: List all users currently attached to '$server'" 474 | fi 475 | if [ "$allow_kick_user" == "true" ]; then 476 | echo " kick: Disconnect an SSH user, remove their wemux server." 477 | fi 478 | echo "" 479 | echo " [c] config: Open the wemux configuration file in $EDITOR." 480 | echo " [h] help: Display this screen." 481 | echo " no args: Start the wemux server/attach to an existing wemux server." 482 | } 483 | 484 | # Host mode command handling: 485 | # If no command given, call start server. 486 | if [ -z "$1" ]; then 487 | announce_connection "host" start_server 488 | else 489 | case "$1" in 490 | start|s) announce_connection "host" start_server;; 491 | attach|a) announce_connection "host" reattach;; 492 | stop|st) shift; stop_server "$@";; 493 | kill|k) shift; stop_server "$@";; 494 | help|h) display_host_commands;; 495 | join|j) shift; change_server "$@";; 496 | name|n) shift; change_server "$@";; 497 | reset|d) change_server "$default_server_name";; 498 | list|l) list_active_servers;; 499 | users|u) list_all_users;; 500 | summon) summon_mirrored;; 501 | summon_all) summon_all_users;; 502 | setmirrored) mirror_all_users;; 503 | togglemirrored) mirror_toggle;; 504 | kick) kick_user $2;; 505 | status_users) status_users;; 506 | display_users) display_users;; 507 | version|v) display_version;; 508 | conf*|c) $editor /usr/local/etc/wemux.conf;; 509 | *) if ! $wemux "$@"; then 510 | echo "To see a list of wemux commands enter 'wemux help'" 511 | exit 127 512 | fi;; 513 | esac 514 | fi 515 | } 516 | 517 | # Client Mode, used when user is NOT listed in the host_list in /usr/local/etc/wemux.conf 518 | client_mode() { 519 | # Mirror mode, allows the user to view wemux server in read only mode. 520 | mirror_mode() { 521 | if session_exists; then 522 | $wemux attach -t $server -r 523 | else 524 | echo "No wemux server to mirror on '$server'." 525 | return 126 526 | fi 527 | } 528 | 529 | # Pair mode, allows user to interact with wemux server. 530 | pair_mode() { 531 | if [ "$allow_pair_mode" == "true" ]; then 532 | if session_exists; then 533 | $wemux attach -t $server 534 | else 535 | echo "No wemux server to pair with on '$server'." 536 | return 126 537 | fi 538 | else 539 | echo "Pair mode is disabled." 540 | return 126 541 | fi 542 | } 543 | 544 | # Rogue mode, allows user to interact with wemux server and operate 545 | # independently in other windows. 546 | # Will connect to existing rogue session or create one if necessary. 547 | rogue_mode() { 548 | if [ "$allow_rogue_mode" == "true" ]; then 549 | if has_rogue_session; then 550 | $wemux attach -t $client_session 551 | elif session_exists; then 552 | $wemux new-session -d -t $server -s $client_session 553 | $wemux new-window -n $username 554 | $wemux send-keys -t $client_session $@ 555 | $wemux attach -t $client_session 556 | else 557 | echo "No wemux server to go 'rogue' with on '$server'." 558 | return 126 559 | fi 560 | else 561 | echo "Rogue mode is disabled." 562 | return 126 563 | fi 564 | } 565 | 566 | # Log user out of rogue mode, removing their session.. 567 | logout_rogue() { 568 | if [ "$allow_rogue_mode" == "true" ]; then 569 | if has_rogue_session; then 570 | [ "$announce_attach" == "true" ] && $wemux display-message \ 571 | "$username has logged out of rogue mode." 572 | $wemux kill-session -t $client_session 573 | echo "Logged out of rogue mode on '$server'." 574 | else 575 | echo "No wemux server to log out of on '$server'." 576 | return 126 577 | fi 578 | else 579 | echo "Rogue mode is disabled." 580 | return 126 581 | fi 582 | } 583 | 584 | send() { 585 | if [ "$allow_pair_mode" == "true" -o "$allow_rogue_mode" == "true" ]; then 586 | $wemux "$@" 587 | else 588 | echo "Pairing and Rogue mode are off, sending is disabled." 589 | fi 590 | } 591 | 592 | smart_reattach() { 593 | # If default_client_mode has been set to "rogue" in wemux.conf: 594 | if [ "$default_client_mode" == "rogue" ] && [ "$allow_rogue_mode" == "true" ]; then 595 | announce_connection "rogue" rogue_mode 596 | # If default_client_mode has been set to "pair" in wemux.conf: 597 | elif [ "$default_client_mode" == "pair" ] && [ "$allow_pair_mode" == "true" ]; then 598 | announce_connection "pair" pair_mode 599 | elif has_rogue_session && [ "$allow_rogue_mode" == "true" ]; then 600 | announce_connection "rogue" rogue_mode 601 | elif [ "$allow_pair" == "true" ]; then 602 | announce_connection "pair" pair_mode 603 | elif session_exists; then 604 | announce_connection "mirror" $wemux attach -t $server -r 605 | else 606 | echo "No wemux server to attach to on '$server'" 607 | return 126 608 | fi 609 | } 610 | 611 | # Display the commands available in client mode. 612 | display_client_commands() { 613 | echo "wemux version $version" 614 | if [ "$allow_server_change" == "true" ]; then 615 | echo "Current wemux server: $server" 616 | fi 617 | echo "" 618 | echo "Usage: wemux [command]" 619 | echo "To connect to wemux please use one of the following:" 620 | echo "" 621 | echo " [m] mirror: Attach to '$server' in read-only mode." 622 | if [ "$allow_pair_mode" == "true" ]; then 623 | echo " [p] pair: Attach to '$server' in pair mode, which allows editing." 624 | fi 625 | if [ "$allow_rogue_mode" == "true" ]; then 626 | echo " [r] rogue: Attach to '$server' in rogue mode, allowing you to pair" 627 | echo " and also work in other windows independent of the host." 628 | echo " [o] logout: Log out of the current wemux rogue session." 629 | fi 630 | echo "" 631 | if [ "$allow_server_change" == "true" ]; then 632 | echo " [j] join [name]: Join the specified wemux server." 633 | echo " [j] join: Display the current wemux server." 634 | echo " [d] reset: Join default wemux server: $default_server_name" 635 | if [ "$allow_server_list" == "true" ]; then 636 | echo " [l] list: List all currently active wemux servers." 637 | fi 638 | fi 639 | if [ "$allow_user_list" == "true" ]; then 640 | echo " [u] users: List all users currently attached to '$server'" 641 | fi 642 | echo "" 643 | echo " [h] help: Display this screen." 644 | if [ "$default_client_mode" == "rogue" ] && [ "$allow_rogue_mode" == "true" ]; then 645 | echo " no args: Attach to '$server' in rogue mode." 646 | elif [ "$default_client_mode" == "pair" ] && [ "$allow_pair_mode" == "true" ]; then 647 | echo " no args: Attach to '$server' in pair mode." 648 | elif [ "$allow_rogue_mode" == "true" ] && [ "$allow_pair_mode" == "true" ]; then 649 | echo " no args: Attach to rogue session on '$server' if it already exists," 650 | echo " otherwise, attach in pair mode." 651 | elif [ "$allow_rogue_mode" == "true" ] && [ "$allow_pair_mode" == "false" ]; then 652 | echo " no args: Attach to rogue session on '$server' if it already exists," 653 | echo " otherwise, attach in mirror mode." 654 | elif [ "$allow_pair_mode" == "true" ]; then 655 | echo " no args: Attach to '$server' in pair mode." 656 | else 657 | echo " no args: Attach to '$server' in mirror mode." 658 | fi 659 | } 660 | 661 | # Client mode command handling: 662 | # If no command given, call smart_reattach 663 | if [ -z "$1" ]; then 664 | smart_reattach 665 | else 666 | case "$1" in 667 | mirror|m) announce_connection "mirror" mirror_mode;; 668 | pair|p) announce_connection "pair" pair_mode;; 669 | rogue|r) shift; announce_connection "rogue" rogue_mode $@;; 670 | edit|e) announce_connection "rogue" rogue_mode;; 671 | logout|o) logout_rogue;; 672 | stop|s) logout_rogue;; 673 | help|h) display_client_commands;; 674 | join|j) shift; change_server "$@";; 675 | name|n) shift; change_server "$@";; 676 | reset|d) change_server "$default_server_name";; 677 | list|l) list_active_servers;; 678 | users|u) list_users;; 679 | status_users) status_users;; 680 | display_users) display_users;; 681 | version|v) display_version;; 682 | send) send $@;; 683 | *) if ! $wemux "$@"; then 684 | echo "To see a list of wemux commands enter 'wemux help'" 685 | exit 127 686 | fi;; 687 | esac 688 | fi 689 | } 690 | 691 | # Determine the groups the user belongs to 692 | groups_for_user() { 693 | echo $(groups $username | awk -F: "{print \$NF}"); 694 | } 695 | 696 | # Check if current user is listed in the host_list. 697 | user_is_a_host() { 698 | for user in "${host_list[@]}"; do 699 | [[ "$user" == "$username" ]] && return 0 700 | done 701 | 702 | # If the user is not in the host list, check their groups 703 | user_groups="$(groups_for_user)"; 704 | for group in ${host_groups[@]}; do 705 | group_re="\\b${group}\\b" 706 | if [[ $user_groups =~ $group_re ]]; then 707 | return 0 708 | fi 709 | done 710 | 711 | return 1 712 | } 713 | 714 | 715 | allowed_nested_command() { 716 | commands=(togglemirrored setmirrored summon summon_all send users u list l display_users 717 | status_users list-clients kill-sesssion kick version v) 718 | for command in "${commands[@]}"; do 719 | [[ "$command" == "$1" ]] && return 0 720 | done 721 | return 1 722 | } 723 | # Create $wemux variable. 724 | 725 | build_wemux_prefix 726 | 727 | # Don't allow wemux to be run directly within a wemux server. 728 | if [[ "$TMUX" != *$socket* ]] || allowed_nested_command "$1" ; then 729 | # Allow manual override to operate in client mode. 730 | if [ "$1" = "client" ]; then 731 | shift; client_mode "$@" 732 | else 733 | # If user is in host list, use host mode. If not, use client mode. 734 | if user_is_a_host; then 735 | host_mode "$@" 736 | else 737 | client_mode "$@" 738 | fi 739 | fi 740 | elif [[ $@ == "help" ]] || [[ $@ == "h" ]]; then 741 | echo "Most wemux commands can only be run while detached from tmux." 742 | echo "The commands that are available while attached are:" 743 | echo "" 744 | echo "HOST ONLY COMMANDS:" 745 | echo " [s] summon: Summon all mirrored users to your current session." 746 | echo " summonall: Summon all users to your current session." 747 | echo " setmirrored: Set all users to mirror mode to your current session." 748 | echo " togglemirrored: Toggle users between mirror/pair mode." 749 | echo " kick [user]: Kick specified user from the server." 750 | echo "" 751 | echo "GENERAL COMMANDS:" 752 | echo " [u] users: List all attached users" 753 | echo " [l] list: List all wemux servers" 754 | else 755 | echo "You're already attached to the wemux server on '$server'" 756 | echo "wemux does not allow nesting wemux servers directly." 757 | fi 758 | -------------------------------------------------------------------------------- /wemux.conf.example: -------------------------------------------------------------------------------- 1 | ## wemux Configuration: 2 | ## wemux version 3.2.0 3 | ## 4 | ## Uncomment an option (remove the # in front of it) if you would like to change 5 | ## the option from its default setting. 6 | 7 | ####### HOST OPTIONS ####### 8 | 9 | ## All usernames in host_list will use wemux in host mode, allowing 10 | ## them to create wemux servers for other users to attach to. 11 | ## Add the usernames of users who should use wemux in host mode: 12 | ## example: host_list=(zolrath csagan brocksamson) 13 | 14 | ## All users in any of the groups in host_groups will also use wemux in host mode. 15 | ## example: host_groups=(wheel wemux) 16 | 17 | ####### CLIENT OPTIONS ####### 18 | 19 | ## Allow users to attach to the wemux server in pair mode. 20 | ## When set to false, clients will only be able to attach in mirror mode. 21 | ## Defaults to "true" 22 | # allow_pair_mode="false" 23 | 24 | ## Allow users to attach to the wemux server in rogue mode. 25 | ## When set to false, clients will only be able to attach in pair or mirror mode. 26 | ## Defaults to "true" 27 | # allow_rogue_mode="false" 28 | 29 | ## When clients enter 'wemux' with no arguments by default it will attempt to 30 | ## join an existing pair mode session, if there is no pair session it will start 31 | ## a mirror mode session. 32 | ## By setting default_client_mode to "pair", 'wemux' with no arguments will always 33 | ## join a pair mode session, even if it has to create it. 34 | ## Defaults to "mirror" 35 | # default_client_mode="pair" 36 | 37 | ## Allow hosts to kick SSH users from the server and remove the kicked users 38 | ## wemux sessions. 39 | ## Defaults to "true" 40 | # allow_kick_user="false" 41 | 42 | ####### MULTI-HOST OPTIONS ####### 43 | 44 | ## Allow users to change their server for multi-host environments. 45 | ## Defaults to "false" 46 | # allow_server_change="true" 47 | 48 | ## Set name for default wemux server. Will be used with wemux reset and 49 | ## when allow_server_change is disabled. 50 | ## Defaults to "wemux" 51 | # default_server_name="customname" 52 | 53 | ## Allow users to list all currently running wemux sockets/servers. 54 | ## Automatically disabled if allow_server_change="false" 55 | ## Defaults to "true" 56 | # allow_server_list="false" 57 | 58 | ####### ANNOUNCEMENT OPTIONS ####### 59 | 60 | ## Allow users to see list of currently connected wemux users. 61 | ## Defaults to "true" 62 | # allow_user_list="false" 63 | 64 | ## Announce when users attach/detach from a tmux server. 65 | ## Defaults to "true" 66 | # announce_attach="false" 67 | 68 | ## Announce when users change the wemux server they are using. 69 | ## Defaults to "true" 70 | # announce_server_change="false" 71 | 72 | ####### OTHER OPTIONS ####### 73 | 74 | ## Location of tmux socket, will have server name appended to end: 75 | ## Defaults to "/tmp/wemux" 76 | # socket_prefix="/tmp/wemux" 77 | 78 | ## Tmux Options: 79 | ## Defaults to -u to have tmux always attempt to use utf-8 mode. 80 | # options="-u" 81 | --------------------------------------------------------------------------------