Change to use shared process

This commit is contained in:
jun7 2018-05-20 00:51:50 +09:00
parent 1f584b19c8
commit 0377be5f81
6 changed files with 770 additions and 88 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
adblock.so
cssoutput
librun.o
wyebab
testrun
user.css

View File

@ -3,6 +3,9 @@ An adblock extension for [wyeb](https://github.com/jun7/wyeb), also webkit2gtk b
most of code of this are from https://github.com/GNOME/epiphany/tree/master/embed/web-extension
wyebad is shared by clients, So even nowadays, browsers spawn procs for each windows,
wyebad keeps single server proc that makes less memory and less cpu times.
Don't worry, wyeb wills quit automatically when there is no client and 30 secs past.
### usage:
@ -14,9 +17,8 @@ copy **easylist.txt** to ~/.config/wyebadblock/
wyebadblock only checks 'easylist.txt'
Testing element hiding is not supported though,
You can check if it works on http://simple-adblock.com/faq/testing-your-adblocker/
Testing element hiding is not supported though.
### Disabling
@ -64,10 +66,22 @@ and make link from the dir to the wyebadblock as above.
## Element Hiding
Per domain CSS hider rule is not supported and this may crash webkit2gtk.
Per domain CSS hider rule is not supported
make cssoutput
./cssoutput > user.css
wyebab -css > user.css
And add the user.css to your browser as user css.
On wyeb, just copy the user.css to the conf dir.
For wyeb, just copy the user.css to the conf dir.
## Shell
wyebab
Reads stdin outputs to stdout.
blank + enter quits.
wyebab requst_uri + ' ' + page_uri
Outputs result
Keeps server 30 sec

View File

@ -868,6 +868,7 @@ ephy_uri_tester_new (const char *adblock_data_dir)
return EPHY_URI_TESTER (g_object_new (EPHY_TYPE_URI_TESTER, "adblock-data-dir", adblock_data_dir, NULL));
}
/*
static void
ephy_uri_tester_adblock_filters_changed_cb (GSettings *settings,
char *key,
@ -886,12 +887,13 @@ ephy_uri_tester_adblock_filters_changed_cb (GSettings *settings,
tester->adblock_loaded = FALSE;
ephy_uri_tester_load (tester);
}
*/
void
ephy_uri_tester_load (EphyUriTester *tester)
{
GTask *task;
char **trash;
// char **trash;
g_return_if_fail (EPHY_IS_URI_TESTER (tester));
@ -920,90 +922,58 @@ ephy_uri_tester_load (EphyUriTester *tester)
//added
#include <webkit2/webkit-web-extension.h>
#include <stdlib.h>
static EphyUriTester *uri_tester;
static GThread *initt = NULL;
static bool tend = false;
#include <stdbool.h>
static gboolean reqcb (WebKitWebPage *web_page,
WebKitURIRequest *request,
WebKitURIResponse *redirected_response,
gpointer *p)
{
const char *request_uri;
const char *redirected_response_uri;
const char *page_uri;
char *modified_uri = NULL;
EphyUriTestFlags flags = EPHY_URI_TEST_ADBLOCK;
request_uri = webkit_uri_request_get_uri (request);
page_uri = webkit_web_page_get_uri (web_page);
#include "wyebrun.h"
redirected_response_uri = redirected_response ?
webkit_uri_response_get_uri (redirected_response) : NULL;
#define EXE "wyebab"
if ((flags & EPHY_URI_TEST_ADBLOCK) || (flags & EPHY_URI_TEST_HTTPS_EVERYWHERE)) {
char *result;
if (initt)
#if DEBUG
# define D(f, ...) g_print(#f"\n", __VA_ARGS__);
# define DD(a) g_print(#a"\n");
#else
# define D(f, ...) ;
# define DD(a) ;
#endif
#if ISEXT
#include <webkit2/webkit-web-extension.h>
static bool first = true;
static gboolean reqcb(WebKitWebPage *page, WebKitURIRequest *request,
WebKitURIResponse *r, gpointer p)
{
SoupMessageHeaders *head = webkit_uri_request_get_http_headers(request);
if (head || tend)
const char *request_uri = webkit_uri_request_get_uri(request);
const char *page_uri = webkit_web_page_get_uri(page);
if (first)
{
g_thread_join(initt);
initt = NULL;
}
if (webkit_uri_request_get_http_headers(request))
first = false;
else //no head is local data. so haven't to block
return false;
}
result = ephy_uri_tester_rewrite_uri (uri_tester,
modified_uri ? modified_uri : request_uri,
page_uri, flags);
g_free (modified_uri);
if (!result) {
return TRUE;
}
char *req = g_strconcat(request_uri, " ", page_uri, NULL);
char *res = wyebreq(EXE, req);
g_free(req);
modified_uri = result;
} else if (!modified_uri) {
return FALSE;
}
if (!res) return true;
if (g_strcmp0 (request_uri, modified_uri) != 0) {
webkit_uri_request_set_uri (request, modified_uri);
}
g_free (modified_uri);
if (g_strcmp0(request_uri, res))
webkit_uri_request_set_uri(request, res);
return FALSE;
}
static gpointer inittcb(gpointer data)
{
ephy_uri_tester_load(uri_tester);
tend = true;
return NULL;
}
static void initex(WebKitWebExtension *ex, WebKitWebPage *wp)
static void pageinit(WebKitWebExtension *ex, WebKitWebPage *wp)
{
gchar *filter_path = g_build_filename(
g_get_user_config_dir(), APPNAME, "easylist.txt", NULL);
if (g_file_test(filter_path, G_FILE_TEST_EXISTS))
{
if (!filter_file)
{
filter_file = g_file_new_for_path(filter_path);
uri_tester = ephy_uri_tester_new("/foo/bar");
initt = g_thread_new("init", inittcb, NULL);
}
if (wp)
DD(pageinit)
g_signal_connect(wp, "send-request", G_CALLBACK(reqcb), NULL);
}
g_free(filter_path);
}
G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(
WebKitWebExtension *ex, const GVariant *v)
{
@ -1028,18 +998,101 @@ G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(
enable = false;
if (enable)
g_signal_connect(ex, "page-created", G_CALLBACK(initex), NULL);
{
wyebloop(EXE, 30, 24);
g_signal_connect(ex, "page-created", G_CALLBACK(pageinit), NULL);
}
}
#endif
static EphyUriTester *tester = NULL;
static GThread *initt = NULL;
static gpointer inittcb(gpointer data)
{
ephy_uri_tester_load(tester);
return NULL;
}
static void monitorcb(
GFileMonitor *m, GFile *f, GFile *o, GFileMonitorEvent e, gpointer p)
{
if (e == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT ||
e == G_FILE_MONITOR_EVENT_DELETED)
exit(0);
}
static void init()
{
DD(wyebad init)
gchar *path = g_build_filename(
g_get_user_config_dir(), APPNAME, "easylist.txt", NULL);
GFile *gf = g_file_new_for_path(path);
GFileMonitor *gm = g_file_monitor_file(gf,
G_FILE_MONITOR_NONE, NULL, NULL);
g_signal_connect(gm, "changed", G_CALLBACK(monitorcb), NULL);
g_object_unref(gf);
if (g_file_test(path, G_FILE_TEST_EXISTS))
{
filter_file = g_file_new_for_path(path);
tester = ephy_uri_tester_new("/foo/bar");
initt = g_thread_new("init", inittcb, NULL);
}
g_free(path);
}
static char *datafunc(char *req)
{
if (initt)
{
g_thread_join(initt);
initt = NULL;
}
//req uri + ' ' + page uri
gchar **args = g_strsplit(req, " ", 2);
char *ret = !tester ? g_strdup(args[0]) : ephy_uri_tester_rewrite_uri(tester,
args[0], args[1] ?: args[0], EPHY_URI_TEST_ADBLOCK);
g_strfreev(args);
return ret;
}
int main(int argc, char **argv)
{
initex(NULL, NULL);
DD(This bin is compiled with DEBUG=1)
if (argc == 1)
{
wyebclient(argv[0]);
}
else if (g_str_has_prefix(argv[1], WYEBPREFIX))
{
init();
wyebsvr(argc, argv, datafunc);
}
else if (!strcmp(argv[1], "-css"))
{
init();
g_thread_join(initt);
g_print(uri_tester->blockcss->str);
g_print(tester->blockcss->str);
g_print("\n\n\n\n{display: none !important}\n\n\n\n");
// g_print(uri_tester->blockcssprivate->str);
//g_print(tester->blockcssprivate->str);
}
else
{
wyebuntil(argv[0], 30);
g_print("%s", wyebreq(argv[0], argv[1]));
}
exit(0);
}

View File

@ -4,26 +4,51 @@ CFLAGS += -Wno-deprecated-declarations
EXTENSION_DIR=$(DESTDIR)/usr/lib/wyebrowser
DAPPNAME=-DAPPNAME='"wyebadblock"'
all: adblock.so
ifdef DEBUG
DDEBUG=-DDEBUG=${DEBUG}
adblock.so: ephy-uri-tester.c ephy-uri-tester.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -shared -fPIC \
ifneq ($(DEBUG), 0)
CFLAGS += -Wall
endif
endif
all: adblock.so wyebab librun.o testrun
adblock.so: ephy-uri-tester.c ephy-uri-tester.h librun.o makefile
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< librun.o -shared -fPIC \
`pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0` \
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
$(DDEBUG) $(DAPPNAME) -DISEXT
wyebab: ephy-uri-tester.c ephy-uri-tester.h librun.o makefile
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< librun.o \
`pkg-config --cflags --libs glib-2.0 libsoup-2.4` \
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
$(DDEBUG) $(DAPPNAME)
cssoutput: ephy-uri-tester.c ephy-uri-tester.h
librun.o: wyebrun.c wyebrun.h makefile
$(CC) $(CFLAGS) $(LDFLAGS) -c -o $@ $< -fPIC\
`pkg-config --cflags --libs glib-2.0` \
-DDEBUG=0
testrun: wyebrun.c wyebrun.h makefile
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< \
`pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0` \
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
$(DDEBUG) $(DAPPNAME)
`pkg-config --cflags --libs glib-2.0` \
-DDEBUG=1
clean:
rm -f adblock.so
rm -f wyebab
rm -f librun.o
rm -f testrun
install: all
install -Dm755 wyebab $(DESTDIR)/usr/bin/wyebab
install -Dm755 adblock.so $(EXTENSION_DIR)/adblock.so
re: clean all
uninstall:
rm -f $(DESTDIR)/usr/bin/wyebab
rm -f $(EXTENSION_DIR)/adblock.so
-rmdir $(EXTENSION_DIR)

541
wyebrun.c Normal file
View File

@ -0,0 +1,541 @@
/*
Copyright 2018 jun7@hush.mail
This file is part of wyebrun.
wyebrun is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
wyebrun is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with wyebrun. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <glib/gstdio.h>
//getpid
#include <sys/types.h>
#include <unistd.h>
//flock
#include <sys/file.h>
#include "wyebrun.h"
#define ROOTNAME "wyebrun"
#define PREFIX WYEBPREFIX
#define INPUT "wyebinput"
#define PING "wyebping"
#define DUNTIL WYEBDUNTIL
#define DPINGTIME 1000
#define P(f, ...) g_print(#f"\n", __VA_ARGS__);
#if DEBUG
static gint64 start;
# define D(f, ...) g_print(#f"\n", __VA_ARGS__);
# define DD(a) g_print(#a"\n");
#else
# define D(...) ;
# define DD(a) ;
#endif
typedef enum {
//to svr
CSuntil = 'u',
CSdata = 'd',
CSping = 'p',
//to client
CCwoke = 'w',
CCret = 'r', //retrun data
CClost = 'l', //we lost the req
} Com;
//shared
static void fatal(int i)
{
P(\n!!! fatal %d !!!\n, i)
exit(1);
}
static void mkdirif(char *path)
{
char *dir = g_path_get_dirname(path);
if (!g_file_test(dir, G_FILE_TEST_EXISTS))
g_mkdir_with_parents(dir, 0700);
g_free(dir);
}
static char *ipcpath(char *exe, char *name)
{
return g_build_filename(g_get_user_runtime_dir(),
ROOTNAME,exe, name, NULL);
}
static char *preparepp(char *exe, char *name)
{
char *path = ipcpath(exe, name);
if (!g_file_test(path, G_FILE_TEST_EXISTS))
{
mkdirif(path);
mkfifo(path, 0600);
}
return path;
}
static bool ipcsend(char *exe, char *name,
Com type, char *caller, char *data)
{
//D(ipcsend exe:%s name:%s, exe, name)
char *path = preparepp(exe, name);
char *esc = g_strescape(data ?: "", "");
char *line = g_strdup_printf("%c%s:%s\n", type, caller ?: "", esc);
g_free(esc);
int pp = open(path, O_WRONLY | O_NONBLOCK);
bool ret = write(pp, line, strlen(line)) != -1;
g_free(line);
close(pp);
g_free(path);
return ret;
}
static gboolean ipccb(GIOChannel *ch, GIOCondition c, gpointer p);
static GSource *ipcwatch(char *exe, char *name, GMainContext *ctx) {
char *path = preparepp(exe, name);
GIOChannel *io = g_io_channel_new_file(path, "r+", NULL);
GSource *watch = g_io_create_watch(io, G_IO_IN);
g_io_channel_unref(io);
g_source_set_callback(watch, (GSourceFunc)ipccb, NULL, NULL);
g_source_attach(watch, ctx);
g_free(path);
return watch;
}
//@server
static char *svrexe = NULL;
static GMainLoop *sloop = NULL;
static wyebdataf dataf = NULL;
static gboolean quit(gpointer p)
{
DD(\nsvr quits\n)
g_main_loop_quit(sloop);
return false;
}
static void until(int sec)
{
if (!sloop) return;
static guint last = 0;
if (last)
g_source_remove(last);
last = g_timeout_add_full(G_PRIORITY_LOW * 2, sec * 1000, quit, NULL, NULL);
}
static gpointer pingt(gpointer p)
{
GMainContext *ctx = g_main_context_new();
ipcwatch(svrexe, PING, ctx);
g_main_loop_run(g_main_loop_new(ctx, true));
return NULL;
}
void wyebwatch(char *exe, char *caller, wyebdataf func)
{
svrexe = exe;
dataf = func;
until(DUNTIL);
g_thread_new("ping", pingt, NULL);
ipcwatch(exe, INPUT, g_main_context_default());
if (!ipcsend(exe, caller, CCwoke, "", NULL))
fatal(1);
}
static gboolean svrinit(char *caller)
{
wyebwatch(svrexe, caller, dataf);
return false;
}
bool wyebsvr(int argc, char **argv, wyebdataf func)
{
if (argc < 2 || !g_str_has_prefix(argv[1], PREFIX)) return false;
svrexe = argv[0];
dataf = func;
sloop = g_main_loop_new(NULL, false);
g_idle_add((GSourceFunc)svrinit, argv[1]);
g_main_loop_run(sloop);
return true;
}
static void getdata(char *caller, char *req)
{
char *data = dataf(req);
if (!ipcsend(svrexe, caller, CCret, "", data))
fatal(2);
g_free(data);
}
//@client
static GMutex retm;
static GMainLoop *cloop;
static GMainContext *wctx = NULL;
static char *retdata = NULL;
static char *pid()
{
static char *pid = NULL;
if (!pid) pid = g_strdup_printf(PREFIX"%d", getpid());
return pid;
}
static void spawnsvr(char *exe)
{
char **argv = g_new0(char*, 2);
argv[0] = exe;
argv[1] = pid();
GError *err = NULL;
if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, &err))
{
g_print("err %s", err->message);
g_error_free(err);
}
g_free(argv);
}
static gboolean pingloop(gpointer p)
{
if (!ipcsend((char *)p, PING, CSping, pid(), NULL))
g_mutex_unlock(&retm);
return true;
}
static char *pppath = NULL;
static void removepp()
{
remove(pppath);
}
static gpointer watcht(char *exe)
{
wctx = g_main_context_new();
cloop = g_main_loop_new(wctx, true);
GSource *watch = ipcwatch(exe, pid(), wctx);
if (!pppath)
{
pppath = ipcpath(exe, pid());
atexit(removepp);
}
g_mutex_unlock(&retm);
g_main_loop_run(cloop);
g_source_unref(watch);
g_main_context_unref(wctx);
g_main_loop_unref(cloop);
cloop = NULL;
return NULL;
}
static void watchstart(char *exe)
{
g_mutex_lock(&retm);
g_thread_new("watch", (GThreadFunc)watcht, exe);
g_mutex_lock(&retm);
g_mutex_unlock(&retm);
}
static gboolean timeout(gpointer p)
{
g_mutex_unlock(&retm);
return false;
}
static GHashTable *lastsec = NULL;
static void reuntil(char *exe)
{
if (!lastsec) return;
int sec = GPOINTER_TO_INT(
g_hash_table_lookup(lastsec, exe));
if (sec)
wyebuntil(exe, sec);
}
//don't free
static char *request(char *exe, Com type, char *caller, char *req)
{
g_free(retdata);
retdata = NULL;
if (!cloop) watchstart(exe);
if (caller)
g_mutex_lock(&retm);
if (!ipcsend(exe, INPUT, type, caller, req))
{ //svr is not running
char *path = ipcpath(exe, "lock");
if (!g_file_test(path, G_FILE_TEST_EXISTS))
mkdirif(path);
int lock = open(path, O_RDONLY | O_CREAT, S_IRUSR);
g_free(path);
//retry in single proc
if (!ipcsend(exe, INPUT, type, caller, req))
{
if (!caller)
g_mutex_lock(&retm);
GSource *tout = g_timeout_source_new(DUNTIL * 1000);
g_source_set_callback(tout, timeout, NULL, NULL);
g_source_attach(tout, wctx);
spawnsvr(exe);
g_mutex_lock(&retm);
g_mutex_unlock(&retm);
g_source_destroy(tout);
g_source_unref(tout);
//wyebloop doesn't know svr quits
reuntil(exe);
if (caller)
g_mutex_lock(&retm);
if (!ipcsend(exe, INPUT, type, caller, req))
fatal(3); //spawning svr failse is fatal
}
close(lock);
}
if (caller)
{
GSource *ping = g_timeout_source_new(DPINGTIME);
g_source_set_callback(ping, (GSourceFunc)pingloop, exe, NULL);
g_source_attach(ping, wctx); //attach to ping thread
g_mutex_lock(&retm);
g_mutex_unlock(&retm);
g_source_destroy(ping);
g_source_unref(ping);
}
return retdata;
}
char *wyebreq(char *exe, char *req)
{
return request(exe, CSdata, pid(), req);
}
void wyebuntil(char *exe, int sec)
{
if (!lastsec)
lastsec = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_replace(lastsec, exe, GINT_TO_POINTER(sec));
char *str = g_strdup_printf("%d", sec);
request(exe, CSuntil, NULL, str);
g_free(str);
}
typedef struct {
char *exe;
int sec;
} wyebloopt;
static void wlfree(wyebloopt *wl)
{
g_free(wl->exe);
g_free(wl);
}
static gboolean loopcb(wyebloopt *wl)
{
wyebuntil(wl->exe, wl->sec);
return true;
}
guint wyebloop(char *exe, int sec, int loopsec)
{
wyebloopt *wl = g_new(wyebloopt, 1);
wl->exe = g_strdup(exe);
wl->sec = sec;
loopcb(wl);
return g_timeout_add_full(G_PRIORITY_DEFAULT,
loopsec * 1000,
(GSourceFunc)loopcb,
wl,
(GDestroyNotify)wlfree);
}
static gboolean tcinputcb(GIOChannel *ch, GIOCondition c, char *exe)
{
char *line;
g_io_channel_read_line(ch, &line, NULL, NULL, NULL);
if (!line) return true;
g_strstrip(line);
if (!strlen(line))
exit(0);
#if DEBUG
if (!strcmp(line, "l"))
{
start = g_get_monotonic_time();
for (int i = 0; i < 10000; i++)
{
char *is = g_strdup_printf("l%d", i);
//g_print("loop %d ret %s\n", i, wyebreq(exe, is));
wyebreq(exe, is);
g_free(is);
}
gint64 now = g_get_monotonic_time();
D(time %f, (now - start) / 1000000.0)
}
else
g_print("RET is %s\n", wyebreq(exe, line));
#else
g_print("%s\n", wyebreq(exe, line)); //don't free
#endif
g_free(line);
return true;
}
static gboolean tcinit(char *exe)
{
//wyebuntil(exe, 1);
wyebloop(exe, 2, 1);
GIOChannel *io = g_io_channel_unix_new(fileno(stdin));
g_io_add_watch(io, G_IO_IN, (GIOFunc)tcinputcb, exe);
return false;
}
void wyebclient(char *exe)
{
//pid_t getpid(void);
sloop = g_main_loop_new(NULL, false);
g_idle_add((GSourceFunc)tcinit, exe);
g_main_loop_run(sloop);
}
//@ipccb
static GHashTable *orders = NULL;
gboolean ipccb(GIOChannel *ch, GIOCondition c, gpointer p)
{
if (!orders)
orders = g_hash_table_new(g_str_hash, g_str_equal);
char *line;
g_io_channel_read_line(ch, &line, NULL, NULL, NULL);
if (!line) return true;
g_strchomp(line);
char *unesc = g_strcompress(line);
g_free(line);
Com type = *unesc;
char *id = unesc + 1;
char *arg = strstr(unesc, ":");
*arg++ = '\0';
#if DEBUG
static int i = 0;
D(ipccb%d %c/%s/%s;, i++, type ,id ,arg)
#endif
static int lastuntil = DUNTIL;
switch (type) {
//server
case CSuntil:
until(lastuntil = atoi(arg));
break;
case CSdata:
g_hash_table_add(orders, id);
getdata(id, arg);
g_hash_table_remove(orders, id);
until(lastuntil);
break;
case CSping:
if (!g_hash_table_lookup(orders, id))
ipcsend(svrexe, id, CClost, NULL, NULL);
break;
//client
case CCret:
retdata = g_strdup(arg);
case CClost:
case CCwoke:
//g_main_loop_quit(cloop);
g_mutex_unlock(&retm);
break;
}
g_free(unesc);
return true;
}
//test
#if DEBUG
static char *testdata(char *req)
{
//sleep(9);
//g_free(req); //makes crash
static int i = 0;
return g_strdup_printf("%d th dummy data. req is %s", ++i, req);
}
int main(int argc, char **argv)
{
start = g_get_monotonic_time();
// gint64 now = g_get_monotonic_time();
// D(time %ld %ld, now - start, now)
//char path[PATH_MAX] = {0};
//readlink("/proc/self/exe", path, PATH_MAX);
//D(progrname %s, path)
if (!wyebsvr(argc, argv, testdata))
wyebclient(argv[0]);
exit(0);
}
#endif

47
wyebrun.h Normal file
View File

@ -0,0 +1,47 @@
/*
Copyright 2018 jun7@hush.mail
This file is part of wyebrun.
wyebrun is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
wyebrun is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with wyebrun. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WYEBRUN_H
#define _WYEBRUN_H
#define WYEBPREFIX "-wyeb"
#define WYEBDUNTIL 3
//client
//wyebrun spawns the exe if wyebsend failes
char *wyebreq( char *exe, char *req);
void wyebuntil( char *exe, int sec); //keep alive. default is 10s
//loop the wyebuntil. to stop, use g_source_remove
guint wyebloop( char *exe, int sec, int loopsec);
//send stdin to svr and ret data to stdout
//blank and enter exit it
void wyebclient(char *exe);
//server
typedef char *(*wyebdataf)(char *req);
//server is spawned with an arg the caller
bool wyebsvr(int argc, char **argv, wyebdataf func);
//or if there is own GMainLoop
void wyebwatch(char *exe, char *caller, wyebdataf func);
//the caller is used to send the res meaning we are ready.
//3 sec left or client will die
#endif //_WYEBRUN_H