| 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 |