Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 293 lines (215 sloc) 11.331 kB
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
1 # Quick Summary
2
3 * Using the Mac OS X programs *pbpaste* and *pbcopy* under *tmux*
4 does not work.
2c4d0aa @ChrisJohnsen Note lack of need for pasteboard access under Yosemite and El Capitan
authored
5 Other services and unpatched builds of *screen* are also affected.
6 **Note:** Under Yosemite (and later) pasteboard access seems to work
7 fine without the program from this repository.
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
8
9 * Certain undocumented, private API functions can fix the problem.
10
11 * Because the functions are private, undocumented, and unstable (one
12 acquired an extra argument in 10.6), I think using a small wrapper
13 program might be better than patching *tmux*.
14
15 Thus, my wrapper-based workaround:
16
17 1. Compile *reattach-to-user-namespace* from this repository.
18 Make it available in your PATH (or use the absolute pathname in
19 the next step).
20
149acd9 @trevor minor doc styling
trevor authored
21 make reattach-to-user-namespace &&
22 cp reattach-to-user-namespace ~/bin
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
23
3f77b1f @ChrisJohnsen Mention the MacPorts and Homebrew installation methods
authored
24 Alternatively, you can install it with [*MacPorts*][MacPorts] or
25 [*Homebrew*][Homebrew]:
26
27 port install tmux-pasteboard
28
29 brew install reattach-to-user-namespace
30
31 [MacPorts]: http://www.macports.org
32 [Homebrew]: http://brew.sh
33
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
34 1. Configure *tmux* to use this wrapper program to start the shell
35 for each new window.
36
ce5ed9b @trevor minor doc styling
trevor authored
37 In `.tmux.conf`:
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
38
ce5ed9b @trevor minor doc styling
trevor authored
39 set-option -g default-command "reattach-to-user-namespace -l zsh"
9f47b6c @ChrisJohnsen Move the cross-platform configuration to Usage.md
authored
40
41 See the file `Usage.md` for other configuration and usage
42 techniques (conditional use for cross-platform configurations,
43 fine-grained usage, etc.)
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
44
45 1. Restart your *tmux* server (or start a new one, or just
46 reconfigure your existing one).
c3aea83 @ChrisJohnsen README.md: be explicit about kill-server
authored
47
48 To kill your existing *tmux* server (and everything running
49 “inside” it!):
50
ce5ed9b @trevor minor doc styling
trevor authored
51 tmux kill-server
2697c6a @ChrisJohnsen README.md: add Quick Summary
authored
52
53 1. Enjoy being able to use *pbpaste*, *pbcopy*, etc. in new shell
54 windows.
55
351e829 @ChrisJohnsen README.md
authored
56 # Purpose of These Programs
57
58 The programs in this repository were created to diagnose and enable
59 reliable access to the Mac OS X pasteboard for programs run under
60 [*tmux*][1] and unmodified versions of [*screen*][2].
61
cf2918b @ChrisJohnsen Describe non-pasteboard uses
authored
62 See the “Beyond Pasteboard Access” section of the `Usage.md` file
63 for other programs that benefit from the wrapper.
64
351e829 @ChrisJohnsen README.md
authored
65 [1]: http://tmux.sourceforge.net/
66 [2]: http://www.gnu.org/software/screen/
67
68 # Mac OS X Pasteboard Access Under *tmux* And *screen*
69
70 ## The Problem
71
72 The most commonly reported broken behavior is that the [*pbcopy* and
73 *pbpaste*][3] command-line programs that come with Mac OS X fail to
74 function properly when run under *tmux* and (sometimes) under
75 “unpatched” *screen*.
76
77 Apple has patched their builds of *screen* (included with Mac OS X)
78 to fix the problem; the [*screen* “port”][4] in the [MacPorts][5]
79 system has [adopted][6] Apple’s *screen* patches.
80
81 Their *screen* patch allows (for example) the user to create
82 a *screen* session under a normal GUI login session and access the
83 pasteboard (inside the *screen* session) anytime that user is logged
84 into the GUI. Programs that are run in a session of “unpatched” *screen* will
85 only encounter the problem when the *screen* session outlives its
86 parent Mac OS X login session (e.g. a normal GUI login or an SSH
87 login).
88
89 Third-party programs (run under *tmux* or unpatched *screen*) are
90 also affected (e.g. non-GUI builds of [Vim][7] [7.3][8] can access
91 the pasteboard when compiled with the `+clipboard` feature).
92
93 [3]: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/pbcopy.1.html
94 [4]: https://trac.macports.org/browser/trunk/dports/sysutils/screen/Portfile
95 [5]: http://www.macports.org/
96 [6]: https://trac.macports.org/browser/trunk/dports/sysutils/screen/files/patch-screen.c
97 [7]: http://www.vim.org/
98 [8]: http://vimhelp.appspot.com/version7.txt.html#added-7.3
99
100 ## Why Pasteboard Breaks
101
102 ### Access to the Mac OS X Pasteboard Service
103
104 The pasteboard service in Mac OS X is registered in a "bootstrap
105 namespace" (see Apple’s [TN2083][9]). The namespaces exist in
106 a hierarchy: “higher” namespaces include access to “lower”
107 namespaces. A process in a lower namespace can not access higher
108 namespaces. So, all process can access the lowest, “root” bootstrap
109 namespace, but only processes in a higher namespace can access that
110 namespace. Processes created as a part of a Mac OS X login session
111 are automatically included in the user’s “per-user” bootstrap
112 namespace. The pasteboard service is only available to processes in
113 the per-user bootstrap namespace.
114
115 [9]: http://developer.apple.com/library/mac/#technotes/tn2083/_index.html
116
117 ### Interaction with *tmux*
118
119 *tmux* uses the *daemon(3)* library function when starting its
120 server process. In Mac OS X 10.5, Apple changed *daemon(3)* to move
121 the resulting process from its original bootstrap namespace to the
122 root bootstrap namespace. This means that the *tmux* server, and its
123 children, will automatically and uncontrollably lose access to what
124 would have been their original bootstrap namespace (i.e. the one
125 that has access to the pasteboard service).
126
127 ### Interaction with Unpatched *screen*
128
129 The situation with *screen* is a bit different since it does not use
130 *daemon(3)*. Unpatched *screen*, and its children, only lose access
131 to the per-user bootstrap namespace when its parent login session
132 exits.
133
134 ## Solution Space
135
136 Apple (and MacPorts) have already handled *screen*. Apple prevents
137 *screen* from losing access to the per-user bootstrap namespace by
138 “migrating to [the] background session” ([in 10.5][10] using
3564a88 @ChrisJohnsen README.md: escape "bare" underscores
authored
139 *\_vprocmgr\_move\_subset\_to\_user*) or “detach[ing] from console”
140 ([in 10.6][11] using *\_vprocmgr\_detach\_from\_console*). For the
351e829 @ChrisJohnsen README.md
authored
141 purposes of *screen*, both of these let the *screen* process access
142 the per-user bootstrap namespace even after the processes initial
143 Mac OS X login session has ended.
144
145 [10]: http://www.opensource.apple.com/source/screen/screen-12/patches/screen.c.diff
146 [11]: http://www.opensource.apple.com/source/screen/screen-19/screen/screen.c
147
148 ### Patch *tmux*?
149
150 Ideally, we could port Apple’s patch to *tmux*. Practically, there
151 are problems with a direct port.
152
153 The undocumented, private function used in Apple’s 10.6 patch,
3564a88 @ChrisJohnsen README.md: escape "bare" underscores
authored
154 *\_vprocmgr\_detach\_from\_console*, is not effective if called before
351e829 @ChrisJohnsen README.md
authored
155 *daemon(3)* (since it forcibly moves the process to the root
156 bootstrap namespace); if called after *daemon(3)*, it just returns
157 an error.
158
159 The undocumented, private function used in Apple’s 10.5 patch,
3564a88 @ChrisJohnsen README.md: escape "bare" underscores
authored
160 *\_vprocmgr\_move\_subset\_to\_user*, is also available in 10.6 (though
351e829 @ChrisJohnsen README.md
authored
161 an extra parameter has been added to it in 10.6). Again, there is no
162 point in calling it before *daemon(3)*, but it is effective if
163 called after *daemon(3)*.
164
3564a88 @ChrisJohnsen README.md: escape "bare" underscores
authored
165 The functionality of *\_vprocmgr\_move\_subset\_to\_user* seems to be
166 a sort of superset of that of *\_vprocmgr\_detach\_from\_console* in
351e829 @ChrisJohnsen README.md
authored
167 that both move to the `"Background"` session, but the former does
168 some extra work that can attach to a user namespace even if the
169 process has been previously moved out of it.
170
171 So, another approach that works is to call either the private
172 function after invoking a custom *daemon* that does not forcibly
173 move its resulting process to the root bootstrap namespace (*tmux*
174 even already has one).
175
3564a88 @ChrisJohnsen README.md: escape "bare" underscores
authored
176 The fact that the signature of *\_vprocmgr\_move\_subset\_to\_user*
351e829 @ChrisJohnsen README.md
authored
177 changed between 10.5 and 10.6 is a strong indication that Apple sees
178 these functions as part of a private API that is liable to change or
179 become available in any (major?) release. It seems inappropriate to
180 ask upstream *tmux* to incorporate calls to functions such as these.
181 It might be appropriate for MacPorts to apply a patch to its port
182 though.
183
184 ### Use a “Reattaching” Wrapper Program
185
186 While it would be nice to have the *tmux* server itself reattached
187 to the per-user bootstrap namespace, it is probably enough to
188 selectively reattach just some of its children. A small wrapper
189 could do the work of reattaching to the appropriate namespace and
190 then execing some other program that will (eventually) need
191 access to the per-user namespace.
192
193 Such a wrapper could be used to run *pbcopy*, *pbpaste*, *vim*, et
194 cetera. This would require the user to remember to use the wrapper
195 (or write scripts/shell-functions/aliases to always do it; or notice
196 it fail then re-run it under the wrapper).
197
198 A more automated solution that probably covers most of the problem
25a35a9 @ChrisJohnsen README.md: protect emphasis before right single quote
authored
199 scenarios for most users would be to set *tmux*’s `default-command`
351e829 @ChrisJohnsen README.md
authored
200 option so that new windows start shells via the wrapper by default.
201 The major area this would not cover would be commands given directly
202 to `new-session` and `new-window` (there are some other commands
203 that start new children, but those are the major ones).
204
205 # Some New Programs For Your Consideration
206
207 ## The Wrapper Program
208
209 The *reattach-to-user-namespace* program implements the “wrapper”
210 solution described above.
211
212 reattach-to-user-namespace program args...
213
214 Its `-l` option causes it to rewrite the execed program’s `argv[0]` to
215 start with a dash (`-`). Most shells take this as a signal that they should
216 start as “login” shells.
217
218 exec reattach-to-user-namespace -l "$SHELL"
219
220 In `.tmux.conf`:
221
222 set-option -g default-command "reattach-to-user-namespace -l zsh"
223
224 ## The Diagnostic Program
225
226 The *test* program was created to easily examine the effects and
227 interactions of some of the “functions of interest” (primarily
228 *daemon(3)*, and the private “vproc” functions).
229
230 Its arguments are interpreted as instructions to call various
231 functions and/or display some result.
232
233 Examples:
234
235 Emulate calling *pbpaste* under plain *tmux*:
236
237 ./test daemon=sys system=pbpaste
238
239 Emulate a *tmux* patch that would automatically reattach to the user
240 namespace (also equivalent to using the wrapper program under an
241 unpatched *tmux*):
242
243 ./test daemon=sys move-to-user=10.6 system=pbpaste
244
245 Emulate a *tmux* patch that uses compat/daemon.c and “detaches from
246 the console”:
247
248 ./test daemon=ours deatch system=pbpaste
249
250 Demonstrate revocation of access to the per-user bootstrap namespace
251 when the Mac OS X login session ends:
252
253 # while logged into the GUI
254
255 # login session ends before pbpaste happens: failure
256 cp /dev/null /tmp/f &&
257 ssh localhost `pwd`/test \
258 daemon=ours \
259 msg=sleeping... sleep=1 msg='done\ sleeping' \
260 system=pbpaste 2\> /tmp/f &&
261 { cat /tmp/f; tail -f /tmp/f; }
262
263 # pbpaste happens before login session ends: success
264 cp /dev/null /tmp/f &&
265 ssh localhost `pwd`/test \
266 daemon=ours \
267 msg=sleeping... msg='done\ sleeping' \
268 system=pbpaste 2\> /tmp/f \; sleep 1 &&
269 { cat /tmp/f; tail -f /tmp/f; }
270
271 Test workarounds to prevent the above end-of-login revocation:
272
273 # while logged into the GUI
274
275 # emulate tmux patched to move to the user namespace
276 # or, equivalently, unpatched *tmux* and wrapper
277 cp /dev/null /tmp/f &&
278 ssh localhost `pwd`/test \
279 daemon=sys \
280 move-to-user=10.6 \
281 msg=sleeping... sleep=1 msg='done\ sleeping' \
282 system=pbpaste 2\> /tmp/f &&
283 { cat /tmp/f; tail -f /tmp/f; }
284
285 # emuate tmux patched to use compat/daemon + detach
286 cp /dev/null /tmp/f &&
287 ssh localhost `pwd`/test \
288 daemon=ours \
289 detach \
290 msg=sleeping... sleep=1 msg='done\ sleeping' \
291 system=pbpaste 2\> /tmp/f &&
292 { cat /tmp/f; tail -f /tmp/f; }
Something went wrong with that request. Please try again.