diff options
author | Drew DeVault <sir@cmpwn.com> | 2017-12-05 12:35:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-05 12:35:51 -0500 |
commit | 3fe64482bb269a3dcceeaf1107b9d59dc60eb8d0 (patch) | |
tree | 8fea86b5c928d551723426e196405e5f2f25de2e | |
parent | Merge pull request #1500 from acrisci/feature/view-set-position (diff) | |
parent | Remove wlc includes (diff) | |
download | sway-3fe64482bb269a3dcceeaf1107b9d59dc60eb8d0.tar.gz sway-3fe64482bb269a3dcceeaf1107b9d59dc60eb8d0.tar.zst sway-3fe64482bb269a3dcceeaf1107b9d59dc60eb8d0.zip |
Merge pull request #1498 from emersion/config
Add minimal config subsystem
-rw-r--r-- | include/sway/commands.h | 10 | ||||
-rw-r--r-- | include/sway/config.h | 405 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | sway/commands.c | 132 | ||||
-rw-r--r-- | sway/commands/exec.c | 6 | ||||
-rw-r--r-- | sway/commands/exec_always.c | 6 | ||||
-rw-r--r-- | sway/commands/exit.c | 4 | ||||
-rw-r--r-- | sway/config.c | 504 | ||||
-rw-r--r-- | sway/main.c | 21 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/security.c | 18 |
11 files changed, 1091 insertions, 19 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index df5c6859..b1f0423d 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h | |||
@@ -47,6 +47,16 @@ struct cmd_results *checkarg(int argc, const char *name, | |||
47 | */ | 47 | */ |
48 | struct cmd_results *handle_command(char *command); | 48 | struct cmd_results *handle_command(char *command); |
49 | /** | 49 | /** |
50 | * Parse and handles a command during config file loading. | ||
51 | * | ||
52 | * Do not use this under normal conditions. | ||
53 | */ | ||
54 | struct cmd_results *config_command(char *command, enum cmd_status block); | ||
55 | /* | ||
56 | * Parses a command policy rule. | ||
57 | */ | ||
58 | struct cmd_results *config_commands_command(char *exec); | ||
59 | /** | ||
50 | * Allocates a cmd_results object. | 60 | * Allocates a cmd_results object. |
51 | */ | 61 | */ |
52 | struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, const char *error, ...); | 62 | struct cmd_results *cmd_results_new(enum cmd_status status, const char* input, const char *error, ...); |
diff --git a/include/sway/config.h b/include/sway/config.h new file mode 100644 index 00000000..7de85ab7 --- /dev/null +++ b/include/sway/config.h | |||
@@ -0,0 +1,405 @@ | |||
1 | #ifndef _SWAY_CONFIG_H | ||
2 | #define _SWAY_CONFIG_H | ||
3 | |||
4 | #define PID_WORKSPACE_TIMEOUT 60 | ||
5 | |||
6 | #include <libinput.h> | ||
7 | #include <stdint.h> | ||
8 | #include <string.h> | ||
9 | #include <wlr/types/wlr_box.h> | ||
10 | #include <xkbcommon/xkbcommon.h> | ||
11 | #include <time.h> | ||
12 | #include "list.h" | ||
13 | #include "layout.h" | ||
14 | #include "container.h" | ||
15 | |||
16 | /** | ||
17 | * Describes a variable created via the `set` command. | ||
18 | */ | ||
19 | struct sway_variable { | ||
20 | char *name; | ||
21 | char *value; | ||
22 | }; | ||
23 | |||
24 | /** | ||
25 | * A key binding and an associated command. | ||
26 | */ | ||
27 | struct sway_binding { | ||
28 | int order; | ||
29 | bool release; | ||
30 | bool bindcode; | ||
31 | list_t *keys; | ||
32 | uint32_t modifiers; | ||
33 | char *command; | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * A mouse binding and an associated command. | ||
38 | */ | ||
39 | struct sway_mouse_binding { | ||
40 | uint32_t button; | ||
41 | char *command; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * A "mode" of keybindings created via the `mode` command. | ||
46 | */ | ||
47 | struct sway_mode { | ||
48 | char *name; | ||
49 | list_t *bindings; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * libinput options for input devices | ||
54 | */ | ||
55 | struct input_config { | ||
56 | char *identifier; | ||
57 | |||
58 | int accel_profile; | ||
59 | int click_method; | ||
60 | int drag_lock; | ||
61 | int dwt; | ||
62 | int left_handed; | ||
63 | int middle_emulation; | ||
64 | int natural_scroll; | ||
65 | float pointer_accel; | ||
66 | int scroll_method; | ||
67 | int send_events; | ||
68 | int tap; | ||
69 | |||
70 | bool capturable; | ||
71 | struct wlr_box region; | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * Size and position configuration for a particular output. | ||
76 | * | ||
77 | * This is set via the `output` command. | ||
78 | */ | ||
79 | struct output_config { | ||
80 | char *name; | ||
81 | int enabled; | ||
82 | int width, height; | ||
83 | int x, y; | ||
84 | int scale; | ||
85 | char *background; | ||
86 | char *background_option; | ||
87 | }; | ||
88 | |||
89 | /** | ||
90 | * Maps a workspace name to an output name. | ||
91 | * | ||
92 | * Set via `workspace <x> output <y>` | ||
93 | */ | ||
94 | struct workspace_output { | ||
95 | char *output; | ||
96 | char *workspace; | ||
97 | }; | ||
98 | |||
99 | struct pid_workspace { | ||
100 | pid_t *pid; | ||
101 | char *workspace; | ||
102 | time_t *time_added; | ||
103 | }; | ||
104 | |||
105 | struct bar_config { | ||
106 | /** | ||
107 | * One of "dock", "hide", "invisible" | ||
108 | * | ||
109 | * Always visible in dock mode. Visible only when modifier key is held in hide mode. | ||
110 | * Never visible in invisible mode. | ||
111 | */ | ||
112 | char *mode; | ||
113 | /** | ||
114 | * One of "show" or "hide". | ||
115 | * | ||
116 | * In "show" mode, it will always be shown on top of the active workspace. | ||
117 | */ | ||
118 | char *hidden_state; | ||
119 | /** | ||
120 | * Id name used to identify the bar through IPC. | ||
121 | * | ||
122 | * Defaults to bar-x, where x corresponds to the position of the | ||
123 | * embedding bar block in the config file (bar-0, bar-1, ...). | ||
124 | */ | ||
125 | char *id; | ||
126 | uint32_t modifier; | ||
127 | list_t *outputs; | ||
128 | //enum desktop_shell_panel_position position; // TODO | ||
129 | list_t *bindings; | ||
130 | char *status_command; | ||
131 | bool pango_markup; | ||
132 | char *swaybar_command; | ||
133 | char *font; | ||
134 | int height; // -1 not defined | ||
135 | |||
136 | #ifdef ENABLE_TRAY | ||
137 | // Tray | ||
138 | char *tray_output; | ||
139 | char *icon_theme; | ||
140 | uint32_t tray_padding; | ||
141 | uint32_t activate_button; | ||
142 | uint32_t context_button; | ||
143 | uint32_t secondary_button; | ||
144 | #endif | ||
145 | |||
146 | bool workspace_buttons; | ||
147 | bool wrap_scroll; | ||
148 | char *separator_symbol; | ||
149 | bool strip_workspace_numbers; | ||
150 | bool binding_mode_indicator; | ||
151 | bool verbose; | ||
152 | pid_t pid; | ||
153 | struct { | ||
154 | char *background; | ||
155 | char *statusline; | ||
156 | char *separator; | ||
157 | char *focused_background; | ||
158 | char *focused_statusline; | ||
159 | char *focused_separator; | ||
160 | char *focused_workspace_border; | ||
161 | char *focused_workspace_bg; | ||
162 | char *focused_workspace_text; | ||
163 | char *active_workspace_border; | ||
164 | char *active_workspace_bg; | ||
165 | char *active_workspace_text; | ||
166 | char *inactive_workspace_border; | ||
167 | char *inactive_workspace_bg; | ||
168 | char *inactive_workspace_text; | ||
169 | char *urgent_workspace_border; | ||
170 | char *urgent_workspace_bg; | ||
171 | char *urgent_workspace_text; | ||
172 | char *binding_mode_border; | ||
173 | char *binding_mode_bg; | ||
174 | char *binding_mode_text; | ||
175 | } colors; | ||
176 | }; | ||
177 | |||
178 | struct border_colors { | ||
179 | uint32_t border; | ||
180 | uint32_t background; | ||
181 | uint32_t text; | ||
182 | uint32_t indicator; | ||
183 | uint32_t child_border; | ||
184 | }; | ||
185 | |||
186 | enum edge_border_types { | ||
187 | E_NONE, /**< Don't hide edge borders */ | ||
188 | E_VERTICAL, /**< hide vertical edge borders */ | ||
189 | E_HORIZONTAL, /**< hide horizontal edge borders */ | ||
190 | E_BOTH, /**< hide vertical and horizontal edge borders */ | ||
191 | E_SMART /**< hide both if precisely one window is present in workspace */ | ||
192 | }; | ||
193 | |||
194 | enum command_context { | ||
195 | CONTEXT_CONFIG = 1, | ||
196 | CONTEXT_BINDING = 2, | ||
197 | CONTEXT_IPC = 4, | ||
198 | CONTEXT_CRITERIA = 8, | ||
199 | CONTEXT_ALL = 0xFFFFFFFF, | ||
200 | }; | ||
201 | |||
202 | struct command_policy { | ||
203 | char *command; | ||
204 | uint32_t context; | ||
205 | }; | ||
206 | |||
207 | enum secure_feature { | ||
208 | FEATURE_LOCK = 1, | ||
209 | FEATURE_PANEL = 2, | ||
210 | FEATURE_BACKGROUND = 4, | ||
211 | FEATURE_SCREENSHOT = 8, | ||
212 | FEATURE_FULLSCREEN = 16, | ||
213 | FEATURE_KEYBOARD = 32, | ||
214 | FEATURE_MOUSE = 64, | ||
215 | }; | ||
216 | |||
217 | struct feature_policy { | ||
218 | char *program; | ||
219 | uint32_t features; | ||
220 | }; | ||
221 | |||
222 | enum ipc_feature { | ||
223 | IPC_FEATURE_COMMAND = 1, | ||
224 | IPC_FEATURE_GET_WORKSPACES = 2, | ||
225 | IPC_FEATURE_GET_OUTPUTS = 4, | ||
226 | IPC_FEATURE_GET_TREE = 8, | ||
227 | IPC_FEATURE_GET_MARKS = 16, | ||
228 | IPC_FEATURE_GET_BAR_CONFIG = 32, | ||
229 | IPC_FEATURE_GET_VERSION = 64, | ||
230 | IPC_FEATURE_GET_INPUTS = 128, | ||
231 | IPC_FEATURE_EVENT_WORKSPACE = 256, | ||
232 | IPC_FEATURE_EVENT_OUTPUT = 512, | ||
233 | IPC_FEATURE_EVENT_MODE = 1024, | ||
234 | IPC_FEATURE_EVENT_WINDOW = 2048, | ||
235 | IPC_FEATURE_EVENT_BINDING = 4096, | ||
236 | IPC_FEATURE_EVENT_INPUT = 8192, | ||
237 | IPC_FEATURE_GET_CLIPBOARD = 16384, | ||
238 | |||
239 | IPC_FEATURE_ALL_COMMANDS = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 16384, | ||
240 | IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, | ||
241 | |||
242 | IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, | ||
243 | }; | ||
244 | |||
245 | struct ipc_policy { | ||
246 | char *program; | ||
247 | uint32_t features; | ||
248 | }; | ||
249 | |||
250 | /** | ||
251 | * The configuration struct. The result of loading a config file. | ||
252 | */ | ||
253 | struct sway_config { | ||
254 | list_t *symbols; | ||
255 | list_t *modes; | ||
256 | list_t *bars; | ||
257 | list_t *cmd_queue; | ||
258 | list_t *workspace_outputs; | ||
259 | list_t *pid_workspaces; | ||
260 | list_t *output_configs; | ||
261 | list_t *input_configs; | ||
262 | list_t *criteria; | ||
263 | list_t *no_focus; | ||
264 | list_t *active_bar_modifiers; | ||
265 | struct sway_mode *current_mode; | ||
266 | struct bar_config *current_bar; | ||
267 | uint32_t floating_mod; | ||
268 | uint32_t dragging_key; | ||
269 | uint32_t resizing_key; | ||
270 | char *floating_scroll_up_cmd; | ||
271 | char *floating_scroll_down_cmd; | ||
272 | char *floating_scroll_left_cmd; | ||
273 | char *floating_scroll_right_cmd; | ||
274 | enum swayc_layouts default_orientation; | ||
275 | enum swayc_layouts default_layout; | ||
276 | char *font; | ||
277 | int font_height; | ||
278 | |||
279 | // Flags | ||
280 | bool focus_follows_mouse; | ||
281 | bool mouse_warping; | ||
282 | bool force_focus_wrapping; | ||
283 | bool active; | ||
284 | bool failed; | ||
285 | bool reloading; | ||
286 | bool reading; | ||
287 | bool auto_back_and_forth; | ||
288 | bool seamless_mouse; | ||
289 | bool show_marks; | ||
290 | |||
291 | bool edge_gaps; | ||
292 | bool smart_gaps; | ||
293 | int gaps_inner; | ||
294 | int gaps_outer; | ||
295 | |||
296 | list_t *config_chain; | ||
297 | const char *current_config; | ||
298 | |||
299 | enum swayc_border_types border; | ||
300 | enum swayc_border_types floating_border; | ||
301 | int border_thickness; | ||
302 | int floating_border_thickness; | ||
303 | enum edge_border_types hide_edge_borders; | ||
304 | |||
305 | // border colors | ||
306 | struct { | ||
307 | struct border_colors focused; | ||
308 | struct border_colors focused_inactive; | ||
309 | struct border_colors unfocused; | ||
310 | struct border_colors urgent; | ||
311 | struct border_colors placeholder; | ||
312 | uint32_t background; | ||
313 | } border_colors; | ||
314 | |||
315 | // floating view | ||
316 | int32_t floating_maximum_width; | ||
317 | int32_t floating_maximum_height; | ||
318 | int32_t floating_minimum_width; | ||
319 | int32_t floating_minimum_height; | ||
320 | |||
321 | // Security | ||
322 | list_t *command_policies; | ||
323 | list_t *feature_policies; | ||
324 | list_t *ipc_policies; | ||
325 | }; | ||
326 | |||
327 | void pid_workspace_add(struct pid_workspace *pw); | ||
328 | void free_pid_workspace(struct pid_workspace *pw); | ||
329 | |||
330 | /** | ||
331 | * Loads the main config from the given path. is_active should be true when | ||
332 | * reloading the config. | ||
333 | */ | ||
334 | bool load_main_config(const char *path, bool is_active); | ||
335 | |||
336 | /** | ||
337 | * Loads an included config. Can only be used after load_main_config. | ||
338 | */ | ||
339 | bool load_include_configs(const char *path, struct sway_config *config); | ||
340 | |||
341 | /** | ||
342 | * Reads the config from the given FILE. | ||
343 | */ | ||
344 | bool read_config(FILE *file, struct sway_config *config); | ||
345 | |||
346 | /** | ||
347 | * Free config struct | ||
348 | */ | ||
349 | void free_config(struct sway_config *config); | ||
350 | /** | ||
351 | * Does variable replacement for a string based on the config's currently loaded variables. | ||
352 | */ | ||
353 | char *do_var_replacement(char *str); | ||
354 | |||
355 | struct cmd_results *check_security_config(); | ||
356 | |||
357 | int input_identifier_cmp(const void *item, const void *data); | ||
358 | void merge_input_config(struct input_config *dst, struct input_config *src); | ||
359 | void apply_input_config(struct input_config *ic, struct libinput_device *dev); | ||
360 | void free_input_config(struct input_config *ic); | ||
361 | |||
362 | int output_name_cmp(const void *item, const void *data); | ||
363 | void merge_output_config(struct output_config *dst, struct output_config *src); | ||
364 | /** Sets up a WLC output handle based on a given output_config. | ||
365 | */ | ||
366 | void apply_output_config(struct output_config *oc, swayc_t *output); | ||
367 | void free_output_config(struct output_config *oc); | ||
368 | |||
369 | /** | ||
370 | * Updates the list of active bar modifiers | ||
371 | */ | ||
372 | void update_active_bar_modifiers(void); | ||
373 | |||
374 | int workspace_output_cmp_workspace(const void *a, const void *b); | ||
375 | |||
376 | int sway_binding_cmp(const void *a, const void *b); | ||
377 | int sway_binding_cmp_qsort(const void *a, const void *b); | ||
378 | int sway_binding_cmp_keys(const void *a, const void *b); | ||
379 | void free_sway_binding(struct sway_binding *sb); | ||
380 | struct sway_binding *sway_binding_dup(struct sway_binding *sb); | ||
381 | |||
382 | int sway_mouse_binding_cmp(const void *a, const void *b); | ||
383 | int sway_mouse_binding_cmp_qsort(const void *a, const void *b); | ||
384 | int sway_mouse_binding_cmp_buttons(const void *a, const void *b); | ||
385 | void free_sway_mouse_binding(struct sway_mouse_binding *smb); | ||
386 | |||
387 | void load_swaybars(); | ||
388 | void terminate_swaybg(pid_t pid); | ||
389 | |||
390 | /** | ||
391 | * Allocate and initialize default bar configuration. | ||
392 | */ | ||
393 | struct bar_config *default_bar_config(void); | ||
394 | |||
395 | /** | ||
396 | * Global config singleton. | ||
397 | */ | ||
398 | extern struct sway_config *config; | ||
399 | |||
400 | /** | ||
401 | * Config file currently being read. | ||
402 | */ | ||
403 | extern const char *current_config_path; | ||
404 | |||
405 | #endif | ||
diff --git a/meson.build b/meson.build index 695e237e..8e7b98ed 100644 --- a/meson.build +++ b/meson.build | |||
@@ -65,6 +65,8 @@ if a2x.found() | |||
65 | endforeach | 65 | endforeach |
66 | endif | 66 | endif |
67 | 67 | ||
68 | add_project_arguments('-DSYSCONFDIR="/@0@"'.format(sysconfdir), language : 'c') | ||
69 | |||
68 | version = get_option('sway_version') | 70 | version = get_option('sway_version') |
69 | if version != '' | 71 | if version != '' |
70 | version = '"@0@"'.format(version) | 72 | version = '"@0@"'.format(version) |
diff --git a/sway/commands.c b/sway/commands.c index 5fdcdbb6..17638129 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <json-c/json.h> | 8 | #include <json-c/json.h> |
9 | #include "sway/commands.h" | 9 | #include "sway/commands.h" |
10 | #include "sway/config.h" | ||
11 | #include "sway/security.h" | ||
10 | #include "stringop.h" | 12 | #include "stringop.h" |
11 | #include "log.h" | 13 | #include "log.h" |
12 | 14 | ||
@@ -200,6 +202,136 @@ cleanup: | |||
200 | return results; | 202 | return results; |
201 | } | 203 | } |
202 | 204 | ||
205 | // this is like handle_command above, except: | ||
206 | // 1) it ignores empty commands (empty lines) | ||
207 | // 2) it does variable substitution | ||
208 | // 3) it doesn't split commands (because the multiple commands are supposed to | ||
209 | // be chained together) | ||
210 | // 4) handle_command handles all state internally while config_command has some | ||
211 | // state handled outside (notably the block mode, in read_config) | ||
212 | struct cmd_results *config_command(char *exec, enum cmd_status block) { | ||
213 | struct cmd_results *results = NULL; | ||
214 | int argc; | ||
215 | char **argv = split_args(exec, &argc); | ||
216 | if (!argc) { | ||
217 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
218 | goto cleanup; | ||
219 | } | ||
220 | |||
221 | sway_log(L_INFO, "handling config command '%s'", exec); | ||
222 | // Endblock | ||
223 | if (**argv == '}') { | ||
224 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); | ||
225 | goto cleanup; | ||
226 | } | ||
227 | struct cmd_handler *handler = find_handler(argv[0], block); | ||
228 | if (!handler) { | ||
229 | char *input = argv[0] ? argv[0] : "(empty)"; | ||
230 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | ||
231 | goto cleanup; | ||
232 | } | ||
233 | int i; | ||
234 | // Var replacement, for all but first argument of set | ||
235 | // TODO commands | ||
236 | for (i = /*handler->handle == cmd_set ? 2 :*/ 1; i < argc; ++i) { | ||
237 | argv[i] = do_var_replacement(argv[i]); | ||
238 | unescape_string(argv[i]); | ||
239 | } | ||
240 | /* Strip quotes for first argument. | ||
241 | * TODO This part needs to be handled much better */ | ||
242 | if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) { | ||
243 | strip_quotes(argv[1]); | ||
244 | } | ||
245 | if (handler->handle) { | ||
246 | results = handler->handle(argc-1, argv+1); | ||
247 | } else { | ||
248 | results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); | ||
249 | } | ||
250 | |||
251 | cleanup: | ||
252 | free_argv(argc, argv); | ||
253 | return results; | ||
254 | } | ||
255 | |||
256 | struct cmd_results *config_commands_command(char *exec) { | ||
257 | struct cmd_results *results = NULL; | ||
258 | int argc; | ||
259 | char **argv = split_args(exec, &argc); | ||
260 | if (!argc) { | ||
261 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
262 | goto cleanup; | ||
263 | } | ||
264 | |||
265 | // Find handler for the command this is setting a policy for | ||
266 | char *cmd = argv[0]; | ||
267 | |||
268 | if (strcmp(cmd, "}") == 0) { | ||
269 | results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); | ||
270 | goto cleanup; | ||
271 | } | ||
272 | |||
273 | struct cmd_handler *handler = find_handler(cmd, CMD_BLOCK_END); | ||
274 | if (!handler && strcmp(cmd, "*") != 0) { | ||
275 | char *input = cmd ? cmd : "(empty)"; | ||
276 | results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); | ||
277 | goto cleanup; | ||
278 | } | ||
279 | |||
280 | enum command_context context = 0; | ||
281 | |||
282 | struct { | ||
283 | char *name; | ||
284 | enum command_context context; | ||
285 | } context_names[] = { | ||
286 | { "config", CONTEXT_CONFIG }, | ||
287 | { "binding", CONTEXT_BINDING }, | ||
288 | { "ipc", CONTEXT_IPC }, | ||
289 | { "criteria", CONTEXT_CRITERIA }, | ||
290 | { "all", CONTEXT_ALL }, | ||
291 | }; | ||
292 | |||
293 | for (int i = 1; i < argc; ++i) { | ||
294 | size_t j; | ||
295 | for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) { | ||
296 | if (strcmp(context_names[j].name, argv[i]) == 0) { | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | if (j == sizeof(context_names) / sizeof(context_names[0])) { | ||
301 | results = cmd_results_new(CMD_INVALID, cmd, | ||
302 | "Invalid command context %s", argv[i]); | ||
303 | goto cleanup; | ||
304 | } | ||
305 | context |= context_names[j].context; | ||
306 | } | ||
307 | |||
308 | struct command_policy *policy = NULL; | ||
309 | for (int i = 0; i < config->command_policies->length; ++i) { | ||
310 | struct command_policy *p = config->command_policies->items[i]; | ||
311 | if (strcmp(p->command, cmd) == 0) { | ||
312 | policy = p; | ||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | if (!policy) { | ||
317 | policy = alloc_command_policy(cmd); | ||
318 | sway_assert(policy, "Unable to allocate security policy"); | ||
319 | if (policy) { | ||
320 | list_add(config->command_policies, policy); | ||
321 | } | ||
322 | } | ||
323 | policy->context = context; | ||
324 | |||
325 | sway_log(L_INFO, "Set command policy for %s to %d", | ||
326 | policy->command, policy->context); | ||
327 | |||
328 | results = cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
329 | |||
330 | cleanup: | ||
331 | free_argv(argc, argv); | ||
332 | return results; | ||
333 | } | ||
334 | |||
203 | struct cmd_results *cmd_results_new(enum cmd_status status, | 335 | struct cmd_results *cmd_results_new(enum cmd_status status, |
204 | const char *input, const char *format, ...) { | 336 | const char *input, const char *format, ...) { |
205 | struct cmd_results *results = malloc(sizeof(struct cmd_results)); | 337 | struct cmd_results *results = malloc(sizeof(struct cmd_results)); |
diff --git a/sway/commands/exec.c b/sway/commands/exec.c index dd71500a..fbbc4941 100644 --- a/sway/commands/exec.c +++ b/sway/commands/exec.c | |||
@@ -1,16 +1,16 @@ | |||
1 | #include <string.h> | 1 | #include <string.h> |
2 | #include "sway/commands.h" | 2 | #include "sway/commands.h" |
3 | #include "sway/config.h" | ||
3 | #include "log.h" | 4 | #include "log.h" |
4 | #include "stringop.h" | 5 | #include "stringop.h" |
5 | 6 | ||
6 | struct cmd_results *cmd_exec(int argc, char **argv) { | 7 | struct cmd_results *cmd_exec(int argc, char **argv) { |
7 | // TODO: config | 8 | if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); |
8 | /*if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); | ||
9 | if (config->reloading) { | 9 | if (config->reloading) { |
10 | char *args = join_args(argv, argc); | 10 | char *args = join_args(argv, argc); |
11 | sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); | 11 | sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); |
12 | free(args); | 12 | free(args); |
13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 13 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
14 | }*/ | 14 | } |
15 | return cmd_exec_always(argc, argv); | 15 | return cmd_exec_always(argc, argv); |
16 | } | 16 | } |
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 0a252e7b..9527a487 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c | |||
@@ -5,15 +5,15 @@ | |||
5 | #include <sys/wait.h> | 5 | #include <sys/wait.h> |
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include "sway/commands.h" | 7 | #include "sway/commands.h" |
8 | #include "sway/workspace.h" | 8 | #include "sway/config.h" |
9 | #include "sway/container.h" | 9 | #include "sway/container.h" |
10 | #include "sway/workspace.h" | ||
10 | #include "log.h" | 11 | #include "log.h" |
11 | #include "stringop.h" | 12 | #include "stringop.h" |
12 | 13 | ||
13 | struct cmd_results *cmd_exec_always(int argc, char **argv) { | 14 | struct cmd_results *cmd_exec_always(int argc, char **argv) { |
14 | struct cmd_results *error = NULL; | 15 | struct cmd_results *error = NULL; |
15 | // TODO: config | 16 | if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); |
16 | //if (!config->active) return cmd_results_new(CMD_DEFER, NULL, NULL); | ||
17 | if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) { | 17 | if ((error = checkarg(argc, "exec_always", EXPECTED_MORE_THAN, 0))) { |
18 | return error; | 18 | return error; |
19 | } | 19 | } |
diff --git a/sway/commands/exit.c b/sway/commands/exit.c index d294e344..4bb6a97b 100644 --- a/sway/commands/exit.c +++ b/sway/commands/exit.c | |||
@@ -1,19 +1,17 @@ | |||
1 | #include <stddef.h> | 1 | #include <stddef.h> |
2 | #include "sway/commands.h" | 2 | #include "sway/commands.h" |
3 | #include "sway/config.h" | ||
3 | 4 | ||
4 | void sway_terminate(int exit_code); | 5 | void sway_terminate(int exit_code); |
5 | 6 | ||
6 | struct cmd_results *cmd_exit(int argc, char **argv) { | 7 | struct cmd_results *cmd_exit(int argc, char **argv) { |
7 | struct cmd_results *error = NULL; | 8 | struct cmd_results *error = NULL; |
8 | /* TODO | ||
9 | if (config->reading) { | 9 | if (config->reading) { |
10 | return cmd_results_new(CMD_FAILURE, "exit", "Can't be used in config file."); | 10 | return cmd_results_new(CMD_FAILURE, "exit", "Can't be used in config file."); |
11 | } | 11 | } |
12 | */ | ||
13 | if ((error = checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0))) { | 12 | if ((error = checkarg(argc, "exit", EXPECTED_EQUAL_TO, 0))) { |
14 | return error; | 13 | return error; |
15 | } | 14 | } |
16 | sway_terminate(0); | 15 | sway_terminate(0); |
17 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 16 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
18 | } | 17 | } |
19 | |||
diff --git a/sway/config.c b/sway/config.c new file mode 100644 index 00000000..475e8b04 --- /dev/null +++ b/sway/config.c | |||
@@ -0,0 +1,504 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #define _XOPEN_SOURCE 700 | ||
3 | #include <stdio.h> | ||
4 | #include <stdbool.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <unistd.h> | ||
7 | #include <libgen.h> | ||
8 | #include <wordexp.h> | ||
9 | #include <sys/types.h> | ||
10 | #include <sys/wait.h> | ||
11 | #include <sys/stat.h> | ||
12 | #include <signal.h> | ||
13 | #include <libinput.h> | ||
14 | #include <limits.h> | ||
15 | #include <float.h> | ||
16 | #include <dirent.h> | ||
17 | #include <strings.h> | ||
18 | #ifdef __linux__ | ||
19 | #include <linux/input-event-codes.h> | ||
20 | #elif __FreeBSD__ | ||
21 | #include <dev/evdev/input-event-codes.h> | ||
22 | #endif | ||
23 | #include <wlr/types/wlr_output.h> | ||
24 | #include "sway/commands.h" | ||
25 | #include "sway/config.h" | ||
26 | #include "sway/layout.h" | ||
27 | #include "readline.h" | ||
28 | #include "stringop.h" | ||
29 | #include "list.h" | ||
30 | #include "log.h" | ||
31 | |||
32 | struct sway_config *config = NULL; | ||
33 | |||
34 | void free_config(struct sway_config *config) { | ||
35 | // TODO | ||
36 | } | ||
37 | |||
38 | static void config_defaults(struct sway_config *config) { | ||
39 | if (!(config->symbols = create_list())) goto cleanup; | ||
40 | if (!(config->modes = create_list())) goto cleanup; | ||
41 | if (!(config->bars = create_list())) goto cleanup; | ||
42 | if (!(config->workspace_outputs = create_list())) goto cleanup; | ||
43 | if (!(config->pid_workspaces = create_list())) goto cleanup; | ||
44 | if (!(config->criteria = create_list())) goto cleanup; | ||
45 | if (!(config->no_focus = create_list())) goto cleanup; | ||
46 | if (!(config->input_configs = create_list())) goto cleanup; | ||
47 | if (!(config->output_configs = create_list())) goto cleanup; | ||
48 | |||
49 | if (!(config->cmd_queue = create_list())) goto cleanup; | ||
50 | |||
51 | if (!(config->current_mode = malloc(sizeof(struct sway_mode)))) goto cleanup; | ||
52 | if (!(config->current_mode->name = malloc(sizeof("default")))) goto cleanup; | ||
53 | strcpy(config->current_mode->name, "default"); | ||
54 | if (!(config->current_mode->bindings = create_list())) goto cleanup; | ||
55 | list_add(config->modes, config->current_mode); | ||
56 | |||
57 | config->floating_mod = 0; | ||
58 | config->dragging_key = BTN_LEFT; | ||
59 | config->resizing_key = BTN_RIGHT; | ||
60 | if (!(config->floating_scroll_up_cmd = strdup(""))) goto cleanup; | ||
61 | if (!(config->floating_scroll_down_cmd = strdup(""))) goto cleanup; | ||
62 | if (!(config->floating_scroll_left_cmd = strdup(""))) goto cleanup; | ||
63 | if (!(config->floating_scroll_right_cmd = strdup(""))) goto cleanup; | ||
64 | config->default_layout = L_NONE; | ||
65 | config->default_orientation = L_NONE; | ||
66 | if (!(config->font = strdup("monospace 10"))) goto cleanup; | ||
67 | // TODO: border | ||
68 | //config->font_height = get_font_text_height(config->font); | ||
69 | |||
70 | // floating view | ||
71 | config->floating_maximum_width = 0; | ||
72 | config->floating_maximum_height = 0; | ||
73 | config->floating_minimum_width = 75; | ||
74 | config->floating_minimum_height = 50; | ||
75 | |||
76 | // Flags | ||
77 | config->focus_follows_mouse = true; | ||
78 | config->mouse_warping = true; | ||
79 | config->reloading = false; | ||
80 | config->active = false; | ||
81 | config->failed = false; | ||
82 | config->auto_back_and_forth = false; | ||
83 | config->seamless_mouse = true; | ||
84 | config->reading = false; | ||
85 | config->show_marks = true; | ||
86 | |||
87 | config->edge_gaps = true; | ||
88 | config->smart_gaps = false; | ||
89 | config->gaps_inner = 0; | ||
90 | config->gaps_outer = 0; | ||
91 | |||
92 | if (!(config->active_bar_modifiers = create_list())) goto cleanup; | ||
93 | |||
94 | if (!(config->config_chain = create_list())) goto cleanup; | ||
95 | config->current_config = NULL; | ||
96 | |||
97 | // borders | ||
98 | config->border = B_NORMAL; | ||
99 | config->floating_border = B_NORMAL; | ||
100 | config->border_thickness = 2; | ||
101 | config->floating_border_thickness = 2; | ||
102 | config->hide_edge_borders = E_NONE; | ||
103 | |||
104 | // border colors | ||
105 | config->border_colors.focused.border = 0x4C7899FF; | ||
106 | config->border_colors.focused.background = 0x285577FF; | ||
107 | config->border_colors.focused.text = 0xFFFFFFFF; | ||
108 | config->border_colors.focused.indicator = 0x2E9EF4FF; | ||
109 | config->border_colors.focused.child_border = 0x285577FF; | ||
110 | |||
111 | config->border_colors.focused_inactive.border = 0x333333FF; | ||
112 | config->border_colors.focused_inactive.background = 0x5F676AFF; | ||
113 | config->border_colors.focused_inactive.text = 0xFFFFFFFF; | ||
114 | config->border_colors.focused_inactive.indicator = 0x484E50FF; | ||
115 | config->border_colors.focused_inactive.child_border = 0x5F676AFF; | ||
116 | |||
117 | config->border_colors.unfocused.border = 0x333333FF; | ||
118 | config->border_colors.unfocused.background = 0x222222FF; | ||
119 | config->border_colors.unfocused.text = 0x888888FF; | ||
120 | config->border_colors.unfocused.indicator = 0x292D2EFF; | ||
121 | config->border_colors.unfocused.child_border = 0x222222FF; | ||
122 | |||
123 | config->border_colors.urgent.border = 0x2F343AFF; | ||
124 | config->border_colors.urgent.background = 0x900000FF; | ||
125 | config->border_colors.urgent.text = 0xFFFFFFFF; | ||
126 | config->border_colors.urgent.indicator = 0x900000FF; | ||
127 | config->border_colors.urgent.child_border = 0x900000FF; | ||
128 | |||
129 | config->border_colors.placeholder.border = 0x000000FF; | ||
130 | config->border_colors.placeholder.background = 0x0C0C0CFF; | ||
131 | config->border_colors.placeholder.text = 0xFFFFFFFF; | ||
132 | config->border_colors.placeholder.indicator = 0x000000FF; | ||
133 | config->border_colors.placeholder.child_border = 0x0C0C0CFF; | ||
134 | |||
135 | config->border_colors.background = 0xFFFFFFFF; | ||
136 | |||
137 | // Security | ||
138 | if (!(config->command_policies = create_list())) goto cleanup; | ||
139 | if (!(config->feature_policies = create_list())) goto cleanup; | ||
140 | if (!(config->ipc_policies = create_list())) goto cleanup; | ||
141 | |||
142 | return; | ||
143 | cleanup: | ||
144 | sway_abort("Unable to allocate config structures"); | ||
145 | } | ||
146 | |||
147 | static bool file_exists(const char *path) { | ||
148 | return path && access(path, R_OK) != -1; | ||
149 | } | ||
150 | |||
151 | static char *get_config_path(void) { | ||
152 | static const char *config_paths[] = { | ||
153 | "$HOME/.sway/config", | ||
154 | "$XDG_CONFIG_HOME/sway/config", | ||
155 | "$HOME/.i3/config", | ||
156 | "$XDG_CONFIG_HOME/i3/config", | ||
157 | SYSCONFDIR "/sway/config", | ||
158 | SYSCONFDIR "/i3/config", | ||
159 | }; | ||
160 | |||
161 | if (!getenv("XDG_CONFIG_HOME")) { | ||
162 | char *home = getenv("HOME"); | ||
163 | char *config_home = malloc(strlen(home) + strlen("/.config") + 1); | ||
164 | if (!config_home) { | ||
165 | sway_log(L_ERROR, "Unable to allocate $HOME/.config"); | ||
166 | } else { | ||
167 | strcpy(config_home, home); | ||
168 | strcat(config_home, "/.config"); | ||
169 | setenv("XDG_CONFIG_HOME", config_home, 1); | ||
170 | sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); | ||
171 | free(config_home); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | wordexp_t p; | ||
176 | char *path; | ||
177 | |||
178 | int i; | ||
179 | for (i = 0; i < (int)(sizeof(config_paths) / sizeof(char *)); ++i) { | ||
180 | if (wordexp(config_paths[i], &p, 0) == 0) { | ||
181 | path = strdup(p.we_wordv[0]); | ||
182 | wordfree(&p); | ||
183 | if (file_exists(path)) { | ||
184 | return path; | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | return NULL; // Not reached | ||
190 | } | ||
191 | |||
192 | const char *current_config_path; | ||
193 | |||
194 | static bool load_config(const char *path, struct sway_config *config) { | ||
195 | sway_log(L_INFO, "Loading config from %s", path); | ||
196 | current_config_path = path; | ||
197 | |||
198 | struct stat sb; | ||
199 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { | ||
200 | return false; | ||
201 | } | ||
202 | |||
203 | if (path == NULL) { | ||
204 | sway_log(L_ERROR, "Unable to find a config file!"); | ||
205 | return false; | ||
206 | } | ||
207 | |||
208 | FILE *f = fopen(path, "r"); | ||
209 | if (!f) { | ||
210 | sway_log(L_ERROR, "Unable to open %s for reading", path); | ||
211 | return false; | ||
212 | } | ||
213 | |||
214 | bool config_load_success = read_config(f, config); | ||
215 | fclose(f); | ||
216 | |||
217 | if (!config_load_success) { | ||
218 | sway_log(L_ERROR, "Error(s) loading config!"); | ||
219 | } | ||
220 | |||
221 | current_config_path = NULL; | ||
222 | return true; | ||
223 | } | ||
224 | |||
225 | static int qstrcmp(const void* a, const void* b) { | ||
226 | return strcmp(*((char**) a), *((char**) b)); | ||
227 | } | ||
228 | |||
229 | bool load_main_config(const char *file, bool is_active) { | ||
230 | char *path; | ||
231 | if (file != NULL) { | ||
232 | path = strdup(file); | ||
233 | } else { | ||
234 | path = get_config_path(); | ||
235 | } | ||
236 | |||
237 | struct sway_config *old_config = config; | ||
238 | config = calloc(1, sizeof(struct sway_config)); | ||
239 | if (!config) { | ||
240 | sway_abort("Unable to allocate config"); | ||
241 | } | ||
242 | |||
243 | config_defaults(config); | ||
244 | if (is_active) { | ||
245 | sway_log(L_DEBUG, "Performing configuration file reload"); | ||
246 | config->reloading = true; | ||
247 | config->active = true; | ||
248 | } | ||
249 | |||
250 | config->current_config = path; | ||
251 | list_add(config->config_chain, path); | ||
252 | |||
253 | config->reading = true; | ||
254 | |||
255 | // Read security configs | ||
256 | bool success = true; | ||
257 | DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); | ||
258 | if (!dir) { | ||
259 | sway_log(L_ERROR, "%s does not exist, sway will have no security configuration" | ||
260 | " and will probably be broken", SYSCONFDIR "/sway/security.d"); | ||
261 | } else { | ||
262 | list_t *secconfigs = create_list(); | ||
263 | char *base = SYSCONFDIR "/sway/security.d/"; | ||
264 | struct dirent *ent = readdir(dir); | ||
265 | struct stat s; | ||
266 | while (ent != NULL) { | ||
267 | char *_path = malloc(strlen(ent->d_name) + strlen(base) + 1); | ||
268 | strcpy(_path, base); | ||
269 | strcat(_path, ent->d_name); | ||
270 | lstat(_path, &s); | ||
271 | if (S_ISREG(s.st_mode) && ent->d_name[0] != '.') { | ||
272 | list_add(secconfigs, _path); | ||
273 | } | ||
274 | else { | ||
275 | free(_path); | ||
276 | } | ||
277 | ent = readdir(dir); | ||
278 | } | ||
279 | closedir(dir); | ||
280 | |||
281 | list_qsort(secconfigs, qstrcmp); | ||
282 | for (int i = 0; i < secconfigs->length; ++i) { | ||
283 | char *_path = secconfigs->items[i]; | ||
284 | if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { | ||
285 | sway_log(L_ERROR, "Refusing to load %s - it must be owned by root and mode 644 or 444", _path); | ||
286 | success = false; | ||
287 | } else { | ||
288 | success = success && load_config(_path, config); | ||
289 | } | ||
290 | } | ||
291 | |||
292 | free_flat_list(secconfigs); | ||
293 | } | ||
294 | |||
295 | success = success && load_config(path, config); | ||
296 | |||
297 | if (is_active) { | ||
298 | config->reloading = false; | ||
299 | } | ||
300 | |||
301 | if (old_config) { | ||
302 | free_config(old_config); | ||
303 | } | ||
304 | config->reading = false; | ||
305 | |||
306 | if (success) { | ||
307 | // TODO: bar | ||
308 | //update_active_bar_modifiers(); | ||
309 | } | ||
310 | |||
311 | return success; | ||
312 | } | ||
313 | |||
314 | bool read_config(FILE *file, struct sway_config *config) { | ||
315 | bool success = true; | ||
316 | enum cmd_status block = CMD_BLOCK_END; | ||
317 | |||
318 | int line_number = 0; | ||
319 | char *line; | ||
320 | while (!feof(file)) { | ||
321 | line = read_line(file); | ||
322 | if (!line) { | ||
323 | continue; | ||
324 | } | ||
325 | line_number++; | ||
326 | line = strip_whitespace(line); | ||
327 | if (line[0] == '#') { | ||
328 | free(line); | ||
329 | continue; | ||
330 | } | ||
331 | struct cmd_results *res; | ||
332 | if (block == CMD_BLOCK_COMMANDS) { | ||
333 | // Special case | ||
334 | res = config_commands_command(line); | ||
335 | } else { | ||
336 | res = config_command(line, block); | ||
337 | } | ||
338 | switch(res->status) { | ||
339 | case CMD_FAILURE: | ||
340 | case CMD_INVALID: | ||
341 | sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, | ||
342 | res->error, config->current_config); | ||
343 | success = false; | ||
344 | break; | ||
345 | |||
346 | case CMD_DEFER: | ||
347 | sway_log(L_DEBUG, "Defferring command `%s'", line); | ||
348 | list_add(config->cmd_queue, strdup(line)); | ||
349 | break; | ||
350 | |||
351 | case CMD_BLOCK_MODE: | ||
352 | if (block == CMD_BLOCK_END) { | ||
353 | block = CMD_BLOCK_MODE; | ||
354 | } else { | ||
355 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
356 | } | ||
357 | break; | ||
358 | |||
359 | case CMD_BLOCK_INPUT: | ||
360 | if (block == CMD_BLOCK_END) { | ||
361 | block = CMD_BLOCK_INPUT; | ||
362 | } else { | ||
363 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
364 | } | ||
365 | break; | ||
366 | |||
367 | case CMD_BLOCK_BAR: | ||
368 | if (block == CMD_BLOCK_END) { | ||
369 | block = CMD_BLOCK_BAR; | ||
370 | } else { | ||
371 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
372 | } | ||
373 | break; | ||
374 | |||
375 | case CMD_BLOCK_BAR_COLORS: | ||
376 | if (block == CMD_BLOCK_BAR) { | ||
377 | block = CMD_BLOCK_BAR_COLORS; | ||
378 | } else { | ||
379 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
380 | } | ||
381 | break; | ||
382 | |||
383 | case CMD_BLOCK_COMMANDS: | ||
384 | if (block == CMD_BLOCK_END) { | ||
385 | block = CMD_BLOCK_COMMANDS; | ||
386 | } else { | ||
387 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
388 | } | ||
389 | break; | ||
390 | |||
391 | case CMD_BLOCK_IPC: | ||
392 | if (block == CMD_BLOCK_END) { | ||
393 | block = CMD_BLOCK_IPC; | ||
394 | } else { | ||
395 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
396 | } | ||
397 | break; | ||
398 | |||
399 | case CMD_BLOCK_IPC_EVENTS: | ||
400 | if (block == CMD_BLOCK_IPC) { | ||
401 | block = CMD_BLOCK_IPC_EVENTS; | ||
402 | } else { | ||
403 | sway_log(L_ERROR, "Invalid block '%s'", line); | ||
404 | } | ||
405 | break; | ||
406 | |||
407 | case CMD_BLOCK_END: | ||
408 | switch(block) { | ||
409 | case CMD_BLOCK_MODE: | ||
410 | sway_log(L_DEBUG, "End of mode block"); | ||
411 | config->current_mode = config->modes->items[0]; | ||
412 | block = CMD_BLOCK_END; | ||
413 | break; | ||
414 | |||
415 | case CMD_BLOCK_INPUT: | ||
416 | sway_log(L_DEBUG, "End of input block"); | ||
417 | // TODO: input | ||
418 | //current_input_config = NULL; | ||
419 | block = CMD_BLOCK_END; | ||
420 | break; | ||
421 | |||
422 | case CMD_BLOCK_BAR: | ||
423 | sway_log(L_DEBUG, "End of bar block"); | ||
424 | config->current_bar = NULL; | ||
425 | block = CMD_BLOCK_END; | ||
426 | break; | ||
427 | |||
428 | case CMD_BLOCK_BAR_COLORS: | ||
429 | sway_log(L_DEBUG, "End of bar colors block"); | ||
430 | block = CMD_BLOCK_BAR; | ||
431 | break; | ||
432 | |||
433 | case CMD_BLOCK_COMMANDS: | ||
434 | sway_log(L_DEBUG, "End of commands block"); | ||
435 | block = CMD_BLOCK_END; | ||
436 | break; | ||
437 | |||
438 | case CMD_BLOCK_IPC: | ||
439 | sway_log(L_DEBUG, "End of IPC block"); | ||
440 | block = CMD_BLOCK_END; | ||
441 | break; | ||
442 | |||
443 | case CMD_BLOCK_IPC_EVENTS: | ||
444 | sway_log(L_DEBUG, "End of IPC events block"); | ||
445 | block = CMD_BLOCK_IPC; | ||
446 | break; | ||
447 | |||
448 | case CMD_BLOCK_END: | ||
449 | sway_log(L_ERROR, "Unmatched }"); | ||
450 | break; | ||
451 | |||
452 | default:; | ||
453 | } | ||
454 | default:; | ||
455 | } | ||
456 | free(line); | ||
457 | free_cmd_results(res); | ||
458 | } | ||
459 | |||
460 | return success; | ||
461 | } | ||
462 | |||
463 | char *do_var_replacement(char *str) { | ||
464 | int i; | ||
465 | char *find = str; | ||
466 | while ((find = strchr(find, '$'))) { | ||
467 | // Skip if escaped. | ||
468 | if (find > str && find[-1] == '\\') { | ||
469 | if (find == str + 1 || !(find > str + 1 && find[-2] == '\\')) { | ||
470 | ++find; | ||
471 | continue; | ||
472 | } | ||
473 | } | ||
474 | // Find matching variable | ||
475 | for (i = 0; i < config->symbols->length; ++i) { | ||
476 | struct sway_variable *var = config->symbols->items[i]; | ||
477 | int vnlen = strlen(var->name); | ||
478 | if (strncmp(find, var->name, vnlen) == 0) { | ||
479 | int vvlen = strlen(var->value); | ||
480 | char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); | ||
481 | if (!newstr) { | ||
482 | sway_log(L_ERROR, | ||
483 | "Unable to allocate replacement during variable expansion"); | ||
484 | break; | ||
485 | } | ||
486 | char *newptr = newstr; | ||
487 | int offset = find - str; | ||
488 | strncpy(newptr, str, offset); | ||
489 | newptr += offset; | ||
490 | strncpy(newptr, var->value, vvlen); | ||
491 | newptr += vvlen; | ||
492 | strcpy(newptr, find + vnlen); | ||
493 | free(str); | ||
494 | str = newstr; | ||
495 | find = str + offset + vvlen; | ||
496 | break; | ||
497 | } | ||
498 | } | ||
499 | if (i == config->symbols->length) { | ||
500 | ++find; | ||
501 | } | ||
502 | } | ||
503 | return str; | ||
504 | } | ||
diff --git a/sway/main.c b/sway/main.c index bc107309..bc843591 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <sys/capability.h> | 15 | #include <sys/capability.h> |
16 | #include <sys/prctl.h> | 16 | #include <sys/prctl.h> |
17 | #endif | 17 | #endif |
18 | #include "sway/config.h" | ||
18 | #include "sway/server.h" | 19 | #include "sway/server.h" |
19 | #include "sway/layout.h" | 20 | #include "sway/layout.h" |
20 | #include "sway/ipc-server.h" | 21 | #include "sway/ipc-server.h" |
@@ -388,14 +389,14 @@ int main(int argc, char **argv) { | |||
388 | ipc_init(&server); | 389 | ipc_init(&server); |
389 | log_env(); | 390 | log_env(); |
390 | 391 | ||
391 | //if (validate) { | 392 | if (validate) { |
392 | // bool valid = load_main_config(config_path, false); | 393 | bool valid = load_main_config(config_path, false); |
393 | // return valid ? 0 : 1; | 394 | return valid ? 0 : 1; |
394 | //} | 395 | } |
395 | 396 | ||
396 | //if (!load_main_config(config_path, false)) { | 397 | if (!load_main_config(config_path, false)) { |
397 | // sway_terminate(EXIT_FAILURE); | 398 | sway_terminate(EXIT_FAILURE); |
398 | //} | 399 | } |
399 | 400 | ||
400 | if (config_path) { | 401 | if (config_path) { |
401 | free(config_path); | 402 | free(config_path); |
@@ -411,9 +412,9 @@ int main(int argc, char **argv) { | |||
411 | 412 | ||
412 | ipc_terminate(); | 413 | ipc_terminate(); |
413 | 414 | ||
414 | //if (config) { | 415 | if (config) { |
415 | // free_config(config); | 416 | free_config(config); |
416 | //} | 417 | } |
417 | 418 | ||
418 | return exit_value; | 419 | return exit_value; |
419 | } | 420 | } |
diff --git a/sway/meson.build b/sway/meson.build index b224f15f..84f48137 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -5,12 +5,14 @@ sway_sources = files( | |||
5 | 'commands/exit.c', | 5 | 'commands/exit.c', |
6 | 'commands/exec.c', | 6 | 'commands/exec.c', |
7 | 'commands/exec_always.c', | 7 | 'commands/exec_always.c', |
8 | 'config.c', | ||
8 | 'ipc-json.c', | 9 | 'ipc-json.c', |
9 | 'ipc-server.c', | 10 | 'ipc-server.c', |
10 | 'desktop/output.c', | 11 | 'desktop/output.c', |
11 | 'desktop/wl_shell.c', | 12 | 'desktop/wl_shell.c', |
12 | 'desktop/xdg_shell_v6.c', | 13 | 'desktop/xdg_shell_v6.c', |
13 | 'desktop/xwayland.c', | 14 | 'desktop/xwayland.c', |
15 | 'security.c', | ||
14 | 'tree/container.c', | 16 | 'tree/container.c', |
15 | 'tree/layout.c', | 17 | 'tree/layout.c', |
16 | 'tree/workspace.c', | 18 | 'tree/workspace.c', |
diff --git a/sway/security.c b/sway/security.c new file mode 100644 index 00000000..cc0d3f66 --- /dev/null +++ b/sway/security.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include "sway/security.h" | ||
5 | |||
6 | struct command_policy *alloc_command_policy(const char *command) { | ||
7 | struct command_policy *policy = malloc(sizeof(struct command_policy)); | ||
8 | if (!policy) { | ||
9 | return NULL; | ||
10 | } | ||
11 | policy->command = strdup(command); | ||
12 | if (!policy->command) { | ||
13 | free(policy); | ||
14 | return NULL; | ||
15 | } | ||
16 | policy->context = 0; | ||
17 | return policy; | ||
18 | } | ||