surf-fifo-20220310-c5c1646.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
surf-fifo-20220310-c5c1646.diff (8358B) | |
--- | |
1 From c5c1646470c4a278a9e44dc3934b4e0346518d40 Mon Sep 17 00:00:00 2001 | |
2 From: avalonwilliams <[email protected]> | |
3 Date: Wed, 9 Mar 2022 23:53:08 -0500 | |
4 Subject: [PATCH] fifo patch | |
5 | |
6 Adds a small command language for remote control of surf through | |
7 a fifo pipe, allowing for more complex scripts and features to be | |
8 added through shell scripts. Also adds a javascript injection function | |
9 that you can bind keys to. | |
10 --- | |
11 config.def.h | 1 + | |
12 surf.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++ | |
13 2 files changed, 211 insertions(+) | |
14 | |
15 diff --git a/config.def.h b/config.def.h | |
16 index 1355ba3..dcc8d64 100644 | |
17 --- a/config.def.h | |
18 +++ b/config.def.h | |
19 @@ -6,6 +6,7 @@ static char *styledir = "~/.surf/styles/"; | |
20 static char *certdir = "~/.surf/certificates/"; | |
21 static char *cachedir = "~/.surf/cache/"; | |
22 static char *cookiefile = "~/.surf/cookies.txt"; | |
23 +static char *fifodir = "~/.surf/fifo/"; | |
24 | |
25 /* Webkit default features */ | |
26 /* Highest priority value will be used. | |
27 diff --git a/surf.c b/surf.c | |
28 index 03d8242..327698e 100644 | |
29 --- a/surf.c | |
30 +++ b/surf.c | |
31 @@ -17,6 +17,8 @@ | |
32 #include <stdlib.h> | |
33 #include <string.h> | |
34 #include <unistd.h> | |
35 +#include <sys/types.h> | |
36 +#include <sys/stat.h> | |
37 | |
38 #include <gdk/gdk.h> | |
39 #include <gdk/gdkkeysyms.h> | |
40 @@ -141,6 +143,24 @@ typedef struct { | |
41 regex_t re; | |
42 } SiteSpecific; | |
43 | |
44 +typedef enum { | |
45 + ARGTYPE_INT, | |
46 + ARGTYPE_FLT, | |
47 + ARGTYPE_STR, | |
48 + ARGTYPE_NIL, | |
49 +} ArgType; | |
50 + | |
51 +typedef struct { | |
52 + char *cmd; | |
53 + void (*func)(Client *c, const Arg *a); | |
54 + ArgType t; | |
55 +} Cmd; | |
56 + | |
57 +typedef struct { | |
58 + char *p; | |
59 + ParamName pv; | |
60 +} ParamMap; | |
61 + | |
62 /* Surf */ | |
63 static void die(const char *errstr, ...); | |
64 static void usage(void); | |
65 @@ -239,6 +259,13 @@ static void clicknavigate(Client *c, const Arg *a, … | |
66 static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult… | |
67 static void clickexternplayer(Client *c, const Arg *a, WebKitHitTestRes… | |
68 | |
69 +static gboolean init_fifo(Client *c); | |
70 +static gboolean start_fifo(Client *c, char *path); | |
71 +static void fifo_read_cb(GObject *f, GAsyncResult *r, gpointer d); | |
72 +static void dispatchcmd(Client *c, char *cmd, char *a); | |
73 +static void injectjs(Client *c, const Arg *a); | |
74 +static void togglewrapper(Client *c, const Arg *a); | |
75 + | |
76 static char winid[64]; | |
77 static char togglestats[11]; | |
78 static char pagestats[2]; | |
79 @@ -255,6 +282,7 @@ static Parameter *curconfig; | |
80 static int modparams[ParameterLast]; | |
81 static int spair[2]; | |
82 char *argv0; | |
83 +static GFile *fifof; | |
84 | |
85 static ParamName loadtransient[] = { | |
86 Certificate, | |
87 @@ -298,6 +326,45 @@ static ParamName loadfinished[] = { | |
88 ParameterLast | |
89 }; | |
90 | |
91 +static ParamMap paramnames[] = { | |
92 + { "autoplay", MediaManualPlay }, | |
93 + { "caret", CaretBrowsing }, | |
94 + { "frameflat", FrameFlattening }, | |
95 + { "geolocation", Geolocation }, | |
96 + { "hidebg", HideBackground }, | |
97 + { "images", LoadImages }, | |
98 + { "indicators", ShowIndicators }, | |
99 + { "java", Java }, | |
100 + { "js", JavaScript }, | |
101 + { "kiosk", KioskMode }, | |
102 + { "microphone", AccessMicrophone }, | |
103 + { "scrollbars", ScrollBars }, | |
104 + { "smoothscroll", SmoothScrolling }, | |
105 + { "spellcheck", SpellChecking }, | |
106 + { "stricttls", StrictTLS }, | |
107 + { "style", Style }, | |
108 + { "webcam", AccessWebcam }, | |
109 + { "webgl", WebGL }, | |
110 +}; | |
111 + | |
112 +static Cmd commands[] = { | |
113 + { "clipboard", clipboard, ARGTYPE_INT }, | |
114 + { "find", find, ARGTYPE_INT }, | |
115 + { "inject", injectjs, ARGTYPE_STR }, | |
116 + { "loaduri", loaduri, ARGTYPE_STR }, | |
117 + { "reload", reload, ARGTYPE_INT }, | |
118 + { "scrollh", scrollh, ARGTYPE_INT }, | |
119 + { "scrollv", scrollv, ARGTYPE_INT }, | |
120 + { "showcert", showcert, ARGTYPE_NIL }, | |
121 + { "spawn", spawn, ARGTYPE_STR }, | |
122 + { "stop", stop, ARGTYPE_NIL }, | |
123 + { "toggle", togglewrapper, ARGTYPE_STR }, | |
124 + { "togglecookies", togglecookiepolicy, ARGTYPE_NIL }, | |
125 + { "togglefullscreen", togglefullscreen, ARGTYPE_NIL }, | |
126 + { "toggleinspector", toggleinspector, ARGTYPE_NIL }, | |
127 + { "zoom", zoom, ARGTYPE_INT }, | |
128 +}; | |
129 + | |
130 /* configuration, allows nested code to access above variables */ | |
131 #include "config.h" | |
132 | |
133 @@ -351,6 +418,7 @@ setup(void) | |
134 cookiefile = buildfile(cookiefile); | |
135 scriptfile = buildfile(scriptfile); | |
136 certdir = buildpath(certdir); | |
137 + fifodir = buildpath(fifodir); | |
138 if (curconfig[Ephemeral].val.i) | |
139 cachedir = NULL; | |
140 else | |
141 @@ -1080,9 +1148,15 @@ destroyclient(Client *c) | |
142 void | |
143 cleanup(void) | |
144 { | |
145 + GError *error = NULL; | |
146 + | |
147 while (clients) | |
148 destroyclient(clients); | |
149 | |
150 + if (fifof != NULL) | |
151 + if (!g_file_delete(fifof, NULL, &error)) | |
152 + g_warning("cleanup: couldn't delete fifo: %s\n"… | |
153 + | |
154 close(spair[0]); | |
155 close(spair[1]); | |
156 g_free(cookiefile); | |
157 @@ -1874,6 +1948,141 @@ msgext(Client *c, char type, const Arg *a) | |
158 c->pageid, type, a->i, ret); | |
159 } | |
160 | |
161 +gboolean | |
162 +init_fifo(Client *c) | |
163 +{ | |
164 + gboolean r = FALSE; | |
165 + char *path = g_strconcat(fifodir, "/", winid, NULL); | |
166 + | |
167 + if (path) { | |
168 + if (g_file_test(path, G_FILE_TEST_EXISTS) && unlink(pat… | |
169 + fprintf(stderr, "surf: couldn't unlink old fifo… | |
170 + | |
171 + if (!mkfifo(path, 0600)) { | |
172 + r = start_fifo(c, path); | |
173 + } else { | |
174 + fprintf(stderr, "init_fifo: couldn't create fif… | |
175 + r = FALSE; | |
176 + } | |
177 + } | |
178 + | |
179 + | |
180 + // fifo info no longer needed | |
181 + g_free(fifodir); | |
182 + if (path) | |
183 + g_free(path); | |
184 + | |
185 + return r; | |
186 +} | |
187 + | |
188 +gboolean | |
189 +start_fifo(Client *c, char *path) | |
190 +{ | |
191 + GError *error = NULL; | |
192 + GFileIOStream *fs; | |
193 + GOutputStream *os; | |
194 + GDataInputStream *is; | |
195 + fifof = g_file_new_for_path (path); | |
196 + | |
197 + /* open in read/write so no blocking occurs */ | |
198 + fs = g_file_open_readwrite(fifof, NULL, &error); | |
199 + if (!fs) { | |
200 + fprintf(stderr, "surf: can't open: %s\n", error->messag… | |
201 + g_error_free(error); | |
202 + return FALSE; | |
203 + } | |
204 + | |
205 + os = g_io_stream_get_output_stream(G_IO_STREAM(fs)); | |
206 + if (!g_output_stream_close(os, NULL, &error)) { | |
207 + fprintf(stderr, "start_fifo: failed to close write end:… | |
208 + error->message); | |
209 + g_error_free(error); | |
210 + return FALSE; | |
211 + } | |
212 + | |
213 + is = g_data_input_stream_new(g_io_stream_get_input_stream(G_IO_… | |
214 + | |
215 + g_data_input_stream_read_line_async(is, G_PRIORITY_DEFAULT, NUL… | |
216 + &fifo_read_cb, c); | |
217 + | |
218 + g_setenv("SURF_FIFO", path, TRUE); | |
219 + | |
220 + return TRUE; | |
221 +} | |
222 + | |
223 +void | |
224 +fifo_read_cb(GObject *f, GAsyncResult *r, gpointer d) | |
225 +{ | |
226 + Client *c = (Client *)d; | |
227 + GDataInputStream *s = (GDataInputStream *)f; | |
228 + GError *error = NULL; | |
229 + gsize length; | |
230 + gchar *rest; | |
231 + | |
232 + gchar *line = g_data_input_stream_read_line_finish(s, r, &lengt… | |
233 + if (error) { | |
234 + fprintf(stderr, "fifo_read_cb: error reading: %s\n", er… | |
235 + return; | |
236 + } | |
237 + | |
238 + if (!line) | |
239 + return; | |
240 + | |
241 + line = strtok_r(line, " ", &rest); | |
242 + | |
243 + dispatchcmd(c, line, rest); | |
244 + | |
245 + g_data_input_stream_read_line_async(s, G_PRIORITY_DEFAULT, NULL, | |
246 + &fifo_read_cb, c); | |
247 +} | |
248 + | |
249 +void | |
250 +dispatchcmd(Client *c, char *cmd, char *a) | |
251 +{ | |
252 + Arg arg; | |
253 + int i; | |
254 + | |
255 + for (i = 0; i < LENGTH(commands); i++) { | |
256 + if (strcmp(cmd, commands[i].cmd) == 0) { | |
257 + switch (commands[i].t) { | |
258 + case ARGTYPE_STR: arg = (Arg)(const void *)a; b… | |
259 + case ARGTYPE_INT: arg = (Arg)atoi(a); b… | |
260 + case ARGTYPE_FLT: arg = (Arg)(float)atof(a); b… | |
261 + case ARGTYPE_NIL: arg = (Arg)0; b… | |
262 + } | |
263 + | |
264 + if (commands[i].t == ARGTYPE_INT) { | |
265 + printf("%i\n", arg.i); | |
266 + } | |
267 + commands[i].func(c, (const Arg *)&arg); | |
268 + return; | |
269 + } | |
270 + } | |
271 + | |
272 + fprintf(stderr, "%s: no such command\n", cmd); | |
273 +} | |
274 + | |
275 +void | |
276 +injectjs(Client *c, const Arg *a) | |
277 +{ | |
278 + evalscript(c, "%s", (char *)a->v); | |
279 +} | |
280 + | |
281 +void | |
282 +togglewrapper(Client *c, const Arg *a) | |
283 +{ | |
284 + int i; | |
285 + | |
286 + for (i = 0; i < LENGTH(paramnames); i++) { | |
287 + if (strcmp(paramnames[i].p, (char *)a->v) == 0) { | |
288 + Arg targ = (Arg)(const void *)paramnames[i].pv; | |
289 + return toggle(c, &targ); | |
290 + } | |
291 + } | |
292 + | |
293 + fprintf(stderr, "toggle: no such setting '%s'", (char *)a->v); | |
294 +} | |
295 + | |
296 void | |
297 scrollv(Client *c, const Arg *a) | |
298 { | |
299 @@ -2123,6 +2332,7 @@ main(int argc, char *argv[]) | |
300 setup(); | |
301 c = newclient(NULL); | |
302 showview(NULL, c); | |
303 + init_fifo(c); | |
304 | |
305 loaduri(c, &arg); | |
306 updatetitle(c); | |
307 -- | |
308 2.35.1 | |
309 |