-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathconsole.txt
More file actions
261 lines (182 loc) · 7.95 KB
/
console.txt
File metadata and controls
261 lines (182 loc) · 7.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
Virtual consoles
~~~~~~~~~~~~~~~~
Or, how do I run Xorg or Wayland?
The primary component that enables GUIs in this project is vtmux, the VT
multiplexer. It runs as a system service, and spawns processes like Xorg
or Wayland compositors, providing them with the access to DRM (monitor
outputs) and input devices. Here's an example of how the relevant part
of the process tree should look like:
1 svhub # top-level supervisor
\
+- vtmux # system service, see startup.txt
\
+- xorgvt # X display 0 on VT1
+- xorgvt # X display 1 on VT3
+- weston # and this one let's say VT5
+- rootsh # bare Linux terminal on VT10
There may be several of these processes running at once, but only one will
be active at a time, showing something on the monitor(s) and getting input
events. This is the "multiplexer" part of vtmux.
Another way to put it is to say that each of these processes "runs on" a
virtual terminal (VT) and vtmux switches between the VTs, mapping one VT
at a time onto the real devices. That's not how it really works in modern
Linux, but it makes for a nice mental model.
Starting vtmux
~~~~~~~~~~~~~~
Typical contents of /etc/svhub/vtmux:
#!/sbin/msh
exec vtmux 3
The argument is the default VT. On startup, vtmux switches to the specified
VT, starting the client there.
Configuring VTs
~~~~~~~~~~~~~~~
The idea with vtmux is to pin particular configurations to particulars VTs.
Example: if VT3 is configured to run Xorg/fluxbox, then every time the user
switches to VT3 with C-A-F3, it would be Xorg with fluxbox. And if say VT5
is Xorg/i3, then C-A-F5 would always bring up Xorg/i3, and same with say
Weston on VT7 or a root shell on a bare Linux console on VT10.
The choice of VTs to configure is arbitrary. It is perfectly fine to have
only VT1, VT5 and VT10; vtmux will refuse to switch to VTs that are not
configured.
Clients are spawned on demand. If the user switches to a configured VT,
but the process is not running there, vtmux will attempt to start it.
Clients are allowed to exit normally (Xorg example: exiting from a wm),
vtmux will just switch off from that VT. Re-entering the same VT would
respawn the client.
Client scripts
~~~~~~~~~~~~~~
The way clients are defined for vtmux is similar to svhub: a script in
a pre-defined directory which vtmux will exec() in a forked process.
Example, say from VT5, would be /etc/vtmux/tty5:
#!/sbin/msh
setenv USER user
setenv HOME /home
setenv SHELL /sbin/cmd
cd $HOME
groups control
setgid $USER
setuid $USER
setenv XDG_RUNTIME_DIR /tmp/$USER
mkdir $XDG_RUNTIME_DIR 0700 $USER:$USER
setenv WESTON_TTY_FD 0
setenv WESTON_LAUNCHER_SOCK 3
waitfor /dev/dri/card0
exec /usr/bin/weston
The clients are spawned with fds 0, 1 and 2 pointing to a matching /dev/ttyN
device, and fd 3 being a communication channel (a socket, see socketpair(2))
back to vtmux, running weston-launch protocol. That's what WESTON_LAUNCHER_SOCK
is in the example above.
Just like with svhub, the scripts are spawned with root uid and must drop
unnecessary privileges. When running under vtmux, clients do *not* need
extra privileges to access DRM or input devices, only the control channel
on fd 3. Running clients as root is a VERY BAD IDEA and may disrupt vtmux
itself among other things.
Some (most?) clients abort if no DRM devices are available during initial
device scan. When a graphics-capable system boots, the first client may get
started before DRM modules finish their initialization and fail instantly.
As a simple workaround, `waitfor` is used to pause script until the first
DRM device appears.
Graphical clients
~~~~~~~~~~~~~~~~~
In order to work properly, graphical clients MUST follow the weston-launch
protocol over the control channel on fd 3 to access DRM and input devices.
Weston supports it out of the box.
Xorg MUST BE PATCHED to work with vtmux.
Other clients probably require patches as well.
This protocol is DIFFERENT from the one logind uses; vtmux DOES NOT support
logind protocol and CANNOT run clients configured for logind only.
For information on the protocol itself, see ./wlaunch.txt.
Non-graphical clients
~~~~~~~~~~~~~~~~~~~~~
Clients that do not use the fd 3 control channel MUST close it.
#!/sbin/msh
close 3 # <-- important!
cd /
setenv PATH "/usr/bin:/bin:/usr/sbin:/sbin"
exec /sbin/cmd
Leaking fd 3 is a low-key security threat, as possession of this fd allows
effectively gives the process DRM mastering capability.
# That said, leaving it open would allow running something like Xorg
# manually from that particular shell, which may be useful for debugging.
This issue is mostly limited to shells running on bare Linux TTYs.
Keyboard control
~~~~~~~~~~~~~~~~
The only way to initiate VT switch with vtmux is to send it a command over
its control socket, /run/ctrl/vtmux. On its own, vtmux does not handle key
events, and disables handling of C-A-Fn combos in the kernel.
Starting vtmux alone actually *disables* C-A-Fn!
That's intentional and there are technical reasons for doing so. For once,
this makes it (relatively) easy to change combos in use, as well as to bind
unusual ones like C-A-Esc for the greeter.
The service that handles keyboard events in this project is keymon.
Relevant parts in /etc/keymon:
C-A-Esc: vtctl 0
C-A-F1: vtctl 1
C-A-F2: vtctl 2
C-A-F3: vtctl 3
C-A-F4: vtctl 4
C-A-F5: vtctl 5
# and the rest if necessary
Like vtmux, keymon a system service and needs to be started during system boot.
Configuring greeter
~~~~~~~~~~~~~~~~~~~
Greeter is just a regular client assigned to non-existent "VT0".
Its client script is /etc/vtmux/tty0. It actually gets spawned on some
high-numbered VT normally not accessible from keyboard, like VT13.
Greeter is what vtmux attempts to switch to without an explicit argument.
When greeter exists, vtmux switches to the last non-greeter VT (that is,
the one the greeter was "called" from).
Greeter is supposed to be used as a DE-independent way of performing
privileged actions like requesting shutdown, putting the system to sleep
and so on.
There is a simple implementation called `ctrlvt` in this project.
It is only meant to be a temporary placeholder, but it give some idea
as to how a greeter is supposed to work.
Starting Xorg
~~~~~~~~~~~~~
Mainline xinit is not compatible with vtmux; `xorgvt` should be used instead.
# Two reasons for this. First, the way X startup works, xinit has to be aware
# of fd 3 and close it for the WM process while leaving it open for the server.
# Second, xinit relies on PATH to find Xorg and on HOME for its scripts, which
# is against the principles of this project. Since xinit is not a particularly
# complex tool, it was deemed easier to replace it with a custom tool instead
# of trying to patch the required behavior into the mainline one.
A viable X session requires two processes to be started as *siblings*:
the X server itself, and the top-level client, typically a window manager.
Here's the relevant part of the process tree:
+- vtmux
\
+- xorgvt
\
+- Xorg
+- window-manager
To get there, vtmux needs to be configured to spawn xorgvt.
/etc/vtmux/tty3:
#!/sbin/msh
setenv USER user
setenv HOME /home
setenv SHELL /sbin/cmd
umask 0000
setenv XDG_RUNTIME_DIR /tmp/$USER
mkdir $XDG_RUNTIME_DIR 0700 $USER:$USER
mkdir /tmp/.X11-unix 01777
umask 0022
cd $HOME
groups control
setgid $USER
setuid $USER
setenv WESTON_TTY_FD 0
setenv WESTON_LAUNCHER_SOCK 3
waitfor /dev/dri/card0
exec /sbin/xorgvt
Then, xorgvt needs to be told how to start the server,
/etc/X11/server:
#!/sbin/msh
exec /usr/bin/Xorg $DISPLAY
and the window manager.
/etc/X11/client:
#!/sbin/msh
/usr/bin/xrdb -retain /etc/X11/xdefaults
exec /usr/bin/fluxbox
The client script is basically the same thing as xinitrc.
See xorgvt man page and comments for more details on this.