surf-fifo-20220310-c5c1646.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
surf-fifo-20220310-c5c1646.diff (8358B)
---
1 From c5c1646470c4a278a9e44dc3934b4e0346518d40 Mon Sep 17 00:00:00 2001
2 From: avalonwilliams <avalonwilliams@protonmail.com>
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, WebKitHitTestResult *h);
66 static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h);
67 static void clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h);
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", error->message);
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(path))
169 + fprintf(stderr, "surf: couldn't unlink old fifo: %s\n", path);
170 +
171 + if (!mkfifo(path, 0600)) {
172 + r = start_fifo(c, path);
173 + } else {
174 + fprintf(stderr, "init_fifo: couldn't create fifo: %s\n", path);
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->message);
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: %s\n",
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_STREAM(fs)));
214 +
215 + g_data_input_stream_read_line_async(is, G_PRIORITY_DEFAULT, NULL,
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, &length, &error);
233 + if (error) {
234 + fprintf(stderr, "fifo_read_cb: error reading: %s\n", error->message);
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; break;
259 + case ARGTYPE_INT: arg = (Arg)atoi(a); break;
260 + case ARGTYPE_FLT: arg = (Arg)(float)atof(a); break;
261 + case ARGTYPE_NIL: arg = (Arg)0; break;
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