From 8e0fb4b8200fbc39a8e1e8891661374969ce2a58 Mon Sep 17 00:00:00 2001 From: TrudeEH Date: Sat, 8 Jun 2024 15:58:05 +0100 Subject: [PATCH] Patch surf --- programs/surf/config.def.h | 21 +- programs/surf/config.h | 21 +- .../surf-dlconsole-20190919-d068a38.diff | 226 ++++++++++++++++++ .../surf-searchengines-20220804-609ea1c.diff | 94 ++++++++ programs/surf/surf | Bin 71568 -> 72192 bytes programs/surf/surf.c | 143 ++++++++--- 6 files changed, 464 insertions(+), 41 deletions(-) create mode 100644 programs/surf/patches/surf-dlconsole-20190919-d068a38.diff create mode 100644 programs/surf/patches/surf-searchengines-20220804-609ea1c.diff diff --git a/programs/surf/config.def.h b/programs/surf/config.def.h index ef447213..8bb427f6 100644 --- a/programs/surf/config.def.h +++ b/programs/surf/config.def.h @@ -6,6 +6,13 @@ static char *styledir = "~/.surf/styles/"; static char *certdir = "~/.surf/certificates/"; static char *cachedir = "~/.surf/cache/"; static char *cookiefile = "~/.surf/cookies.txt"; +static char *dldir = "~/dl/"; +static char *dlstatus = "~/.surf/dlstatus/"; + +static SearchEngine searchengines[] = { + { " ", "https://duckduckgo.com/?q=%s" }, + { "g ", "https://google.com/search?q=%s" }, +}; /* Webkit default features */ /* Highest priority value will be used. @@ -74,13 +81,12 @@ static WebKitFindOptions findopts = WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | } \ } -/* DOWNLOAD(URI, referer) */ -#define DOWNLOAD(u, r) { \ +#define DLSTATUS { \ .v = (const char *[]){ "st", "-e", "/bin/sh", "-c",\ - "curl -g -L -J -O -A \"$1\" -b \"$2\" -c \"$2\"" \ - " -e \"$3\" \"$4\"; read", \ - "surf-download", useragent, cookiefile, r, u, NULL \ - } \ + "while true; do cat $1/* 2>/dev/null || echo \"No downloads yet.\";"\ + "A=; read A; "\ + "if [ $A = \"clean\" ]; then rm $1/*; fi; clear; done",\ + "surf-dlstatus", dlstatus, NULL } \ } /* PLUMB(URI) */ @@ -177,6 +183,9 @@ static Key keys[] = { { MODKEY|GDK_SHIFT_MASK, GDK_KEY_b, toggle, { .i = ScrollBars } }, { MODKEY|GDK_SHIFT_MASK, GDK_KEY_t, toggle, { .i = StrictTLS } }, { MODKEY|GDK_SHIFT_MASK, GDK_KEY_m, toggle, { .i = Style } }, + + /* download-console */ + { MODKEY, GDK_KEY_d, spawndls, { 0 } }, }; /* button definitions */ diff --git a/programs/surf/config.h b/programs/surf/config.h index ef447213..8bb427f6 100644 --- a/programs/surf/config.h +++ b/programs/surf/config.h @@ -6,6 +6,13 @@ static char *styledir = "~/.surf/styles/"; static char *certdir = "~/.surf/certificates/"; static char *cachedir = "~/.surf/cache/"; static char *cookiefile = "~/.surf/cookies.txt"; +static char *dldir = "~/dl/"; +static char *dlstatus = "~/.surf/dlstatus/"; + +static SearchEngine searchengines[] = { + { " ", "https://duckduckgo.com/?q=%s" }, + { "g ", "https://google.com/search?q=%s" }, +}; /* Webkit default features */ /* Highest priority value will be used. @@ -74,13 +81,12 @@ static WebKitFindOptions findopts = WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | } \ } -/* DOWNLOAD(URI, referer) */ -#define DOWNLOAD(u, r) { \ +#define DLSTATUS { \ .v = (const char *[]){ "st", "-e", "/bin/sh", "-c",\ - "curl -g -L -J -O -A \"$1\" -b \"$2\" -c \"$2\"" \ - " -e \"$3\" \"$4\"; read", \ - "surf-download", useragent, cookiefile, r, u, NULL \ - } \ + "while true; do cat $1/* 2>/dev/null || echo \"No downloads yet.\";"\ + "A=; read A; "\ + "if [ $A = \"clean\" ]; then rm $1/*; fi; clear; done",\ + "surf-dlstatus", dlstatus, NULL } \ } /* PLUMB(URI) */ @@ -177,6 +183,9 @@ static Key keys[] = { { MODKEY|GDK_SHIFT_MASK, GDK_KEY_b, toggle, { .i = ScrollBars } }, { MODKEY|GDK_SHIFT_MASK, GDK_KEY_t, toggle, { .i = StrictTLS } }, { MODKEY|GDK_SHIFT_MASK, GDK_KEY_m, toggle, { .i = Style } }, + + /* download-console */ + { MODKEY, GDK_KEY_d, spawndls, { 0 } }, }; /* button definitions */ diff --git a/programs/surf/patches/surf-dlconsole-20190919-d068a38.diff b/programs/surf/patches/surf-dlconsole-20190919-d068a38.diff new file mode 100644 index 00000000..cf605ff0 --- /dev/null +++ b/programs/surf/patches/surf-dlconsole-20190919-d068a38.diff @@ -0,0 +1,226 @@ +From 0ea5ecb238b932c533413b912b7981a737af56cf Mon Sep 17 00:00:00 2001 +From: danoloan10 +Date: Thu, 19 Sep 2019 18:25:59 +0200 +Subject: [PATCH] Basic integrated downloads via console display + +--- + config.def.h | 16 ++++--- + surf.c | 118 +++++++++++++++++++++++++++++++++++++++------------ + 2 files changed, 101 insertions(+), 33 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 34265f6..375be93 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,6 +6,8 @@ static char *styledir = "~/.surf/styles/"; + static char *certdir = "~/.surf/certificates/"; + static char *cachedir = "~/.surf/cache/"; + static char *cookiefile = "~/.surf/cookies.txt"; ++static char *dldir = "~/dl/"; ++static char *dlstatus = "~/.surf/dlstatus/"; + + /* Webkit default features */ + /* Highest priority value will be used. +@@ -76,13 +78,12 @@ static WebKitFindOptions findopts = WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | + } \ + } + +-/* DOWNLOAD(URI, referer) */ +-#define DOWNLOAD(u, r) { \ ++#define DLSTATUS { \ + .v = (const char *[]){ "st", "-e", "/bin/sh", "-c",\ +- "curl -g -L -J -O -A \"$1\" -b \"$2\" -c \"$2\"" \ +- " -e \"$3\" \"$4\"; read", \ +- "surf-download", useragent, cookiefile, r, u, NULL \ +- } \ ++ "while true; do cat $1/* 2>/dev/null || echo \"No downloads yet.\";"\ ++ "A=; read A; "\ ++ "if [ $A = \"clean\" ]; then rm $1/*; fi; clear; done",\ ++ "surf-dlstatus", dlstatus, NULL } \ + } + + /* PLUMB(URI) */ +@@ -180,6 +181,9 @@ static Key keys[] = { + { MODKEY|GDK_SHIFT_MASK, GDK_KEY_b, toggle, { .i = ScrollBars } }, + { MODKEY|GDK_SHIFT_MASK, GDK_KEY_t, toggle, { .i = StrictTLS } }, + { MODKEY|GDK_SHIFT_MASK, GDK_KEY_m, toggle, { .i = Style } }, ++ ++ /* download-console */ ++ { MODKEY, GDK_KEY_d, spawndls, { 0 } }, + }; + + /* button definitions */ +diff --git a/surf.c b/surf.c +index 2b54e3c..771858e 100644 +--- a/surf.c ++++ b/surf.c +@@ -205,10 +205,6 @@ static void decidenewwindow(WebKitPolicyDecision *d, Client *c); + static void decideresource(WebKitPolicyDecision *d, Client *c); + static void insecurecontent(WebKitWebView *v, WebKitInsecureContentEvent e, + Client *c); +-static void downloadstarted(WebKitWebContext *wc, WebKitDownload *d, +- Client *c); +-static void responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c); +-static void download(Client *c, WebKitURIResponse *r); + static void webprocessterminated(WebKitWebView *v, + WebKitWebProcessTerminationReason r, + Client *c); +@@ -237,6 +233,17 @@ static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h); + static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h); + static void clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h); + ++/* download-console */ ++static void downloadstarted(WebKitWebContext *wc, WebKitDownload *d, ++ Client *c); ++static void downloadfailed(WebKitDownload *d, GParamSpec *ps, void *arg); ++static void downloadfinished(WebKitDownload *d, GParamSpec *ps, void *arg); ++static gboolean decidedestination(WebKitDownload *d, ++ gchar *suggested_filename, void *arg); ++static void printprogress(WebKitDownload *d, GParamSpec *ps, void *arg); ++static void logdownload(WebKitDownload *d, gchar *tail); ++static void spawndls(Client *c, const Arg *a); ++ + static char winid[64]; + static char togglestats[12]; + static char pagestats[2]; +@@ -340,6 +347,8 @@ setup(void) + scriptfile = buildfile(scriptfile); + cachedir = buildpath(cachedir); + certdir = buildpath(certdir); ++ dlstatus = buildpath(dlstatus); ++ dldir = buildpath(dldir); + + gdkkb = gdk_seat_get_keyboard(gdk_display_get_default_seat(gdpy)); + +@@ -1079,6 +1088,8 @@ cleanup(void) + g_free(scriptfile); + g_free(stylefile); + g_free(cachedir); ++ g_free(dldir); ++ g_free(dlstatus); + XCloseDisplay(dpy); + } + +@@ -1710,8 +1721,7 @@ decideresource(WebKitPolicyDecision *d, Client *c) + if (webkit_response_policy_decision_is_mime_type_supported(r)) { + webkit_policy_decision_use(d); + } else { +- webkit_policy_decision_ignore(d); +- download(c, res); ++ webkit_policy_decision_download(d); + } + } + +@@ -1721,27 +1731,6 @@ insecurecontent(WebKitWebView *v, WebKitInsecureContentEvent e, Client *c) + c->insecure = 1; + } + +-void +-downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c) +-{ +- g_signal_connect(G_OBJECT(d), "notify::response", +- G_CALLBACK(responsereceived), c); +-} +- +-void +-responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c) +-{ +- download(c, webkit_download_get_response(d)); +- webkit_download_cancel(d); +-} +- +-void +-download(Client *c, WebKitURIResponse *r) +-{ +- Arg a = (Arg)DOWNLOAD(webkit_uri_response_get_uri(r), geturi(c)); +- spawn(c, &a); +-} +- + void + webprocessterminated(WebKitWebView *v, WebKitWebProcessTerminationReason r, + Client *c) +@@ -1971,6 +1960,81 @@ clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h) + spawn(c, &arg); + } + ++/* download-console */ ++ ++void ++downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c) ++{ ++ webkit_download_set_allow_overwrite(d, TRUE); ++ g_signal_connect(G_OBJECT(d), "decide-destination", ++ G_CALLBACK(decidedestination), NULL); ++ g_signal_connect(G_OBJECT(d), "notify::estimated-progress", ++ G_CALLBACK(printprogress), NULL); ++ g_signal_connect(G_OBJECT(d), "failed", ++ G_CALLBACK(downloadfailed), NULL); ++ g_signal_connect(G_OBJECT(d), "finished", ++ G_CALLBACK(downloadfinished), NULL); ++} ++ ++void ++downloadfailed(WebKitDownload *d, GParamSpec *ps, void *arg) ++{ ++ logdownload(d, " -- FAILED"); ++} ++ ++void ++downloadfinished(WebKitDownload *d, GParamSpec *ps, void *arg) ++{ ++ logdownload(d, " -- COMPLETED"); ++} ++ ++gboolean ++decidedestination(WebKitDownload *d, gchar *suggested_filename, void *arg) ++{ ++ gchar *dest; ++ dest = g_strdup_printf("file://%s/%s", dldir, suggested_filename); ++ webkit_download_set_destination(d, dest); ++ return TRUE; ++} ++ ++void ++printprogress(WebKitDownload *d, GParamSpec *ps, void *arg) ++{ ++ logdownload(d, ""); ++} ++ ++void ++logdownload(WebKitDownload *d, gchar *tail) ++{ ++ gchar *filename, *statfile; ++ FILE *stat; ++ ++ filename = g_path_get_basename(webkit_download_get_destination(d)); ++ statfile = g_strdup_printf("%s/%s", dlstatus, filename); ++ ++ if ((stat = fopen(statfile, "w")) == NULL) { ++ perror("dlstatus"); ++ } else { ++ fprintf(stat, "%s: %d%% (%d.%ds)%s\n", ++ filename, ++ (int)(webkit_download_get_estimated_progress(d) * 100), ++ (int) webkit_download_get_elapsed_time(d), ++ (int)(webkit_download_get_elapsed_time(d) * 100), ++ tail); ++ fclose(stat); ++ } ++ ++ g_free(statfile); ++ g_free(filename); ++} ++ ++void ++spawndls(Client *c, const Arg *a) ++{ ++ Arg arg = (Arg)DLSTATUS; ++ spawn(c, &arg); ++} ++ + int + main(int argc, char *argv[]) + { +-- +2.22.1 + diff --git a/programs/surf/patches/surf-searchengines-20220804-609ea1c.diff b/programs/surf/patches/surf-searchengines-20220804-609ea1c.diff new file mode 100644 index 00000000..32aca05e --- /dev/null +++ b/programs/surf/patches/surf-searchengines-20220804-609ea1c.diff @@ -0,0 +1,94 @@ +From 2f64431f15777d93d146707dccdb6ad063c7a316 Mon Sep 17 00:00:00 2001 +From: Justinas Grigas +Date: Thu, 4 Aug 2022 23:18:40 +0300 +Subject: [PATCH] searchengines: allows simple use of search engines + +The previous patches had some issues: +* don't apply cleanly to the latest version. +* a space between the token and query is implied, so having " " as a + token means you actually have to use " ". Or if your token is "e", + searching for "example.com" would trigger it. Now you specify the exact + token to look for. +* has checks to skip badly configured search engines. The correct + solution is to configure them right. + +Now it works like a better version of the spacesearch patch, as it +allows you to specify " " as a token +--- + config.def.h | 5 +++++ + surf.c | 22 +++++++++++++++++++++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index 075f7d0..7bb9c46 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -8,6 +8,11 @@ static char *cachedir = "~/.local/share/surf/cache/"; + static char *cookiefile = "~/.local/share/surf/cookies.txt"; + static char *historyfile = "~/.local/share/surf/history.txt"; + ++static SearchEngine searchengines[] = { ++ { " ", "https://duckduckgo.com/?q=%s" }, ++ { "osrs ", "https://oldschool.runescape.wiki/?search=%s" }, ++}; ++ + /* Webkit default features */ + /* Highest priority value will be used. + * Default parameters are priority 0 +diff --git a/surf.c b/surf.c +index a2b507c..7e85952 100644 +--- a/surf.c ++++ b/surf.c +@@ -133,6 +133,11 @@ typedef struct { + unsigned int stopevent; + } Button; + ++typedef struct { ++ char *token; ++ char *uri; ++} SearchEngine; ++ + typedef struct { + const char *uri; + Parameter config[ParameterLast]; +@@ -220,6 +225,7 @@ static void webprocessterminated(WebKitWebView *v, + Client *c); + static void closeview(WebKitWebView *v, Client *c); + static void destroywin(GtkWidget* w, Client *c); ++static gchar *parseuri(const gchar *uri); + + /* Hotkeys */ + static void pasteuri(GtkClipboard *clipboard, const char *text, gpointer d); +@@ -584,7 +590,7 @@ loaduri(Client *c, const Arg *a) + url = g_strdup_printf("file://%s", path); + free(path); + } else { +- url = g_strdup_printf("http://%s", uri); ++ url = parseuri(uri); + } + if (apath != uri) + free(apath); +@@ -1811,6 +1817,20 @@ destroywin(GtkWidget* w, Client *c) + gtk_main_quit(); + } + ++gchar * ++parseuri(const gchar *uri) ++{ ++ guint i; ++ ++ for (i = 0; i < LENGTH(searchengines); i++) { ++ if (g_str_has_prefix(uri, searchengines[i].token)) ++ return g_strdup_printf(searchengines[i].uri, ++ uri + strlen(searchengines[i].token)); ++ } ++ ++ return g_strdup_printf("http://%s", uri); ++} ++ + void + pasteuri(GtkClipboard *clipboard, const char *text, gpointer d) + { +-- +2.37.1 + diff --git a/programs/surf/surf b/programs/surf/surf index 0d1ba2e1fd80eca1840e03a75561a30f88b7f964..cf81a0e80446508dcfb0b242d9040b95ea35e2ab 100755 GIT binary patch delta 25481 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 diff --git a/programs/surf/surf.c b/programs/surf/surf.c index af0fa742..956718ba 100644 --- a/programs/surf/surf.c +++ b/programs/surf/surf.c @@ -129,6 +129,11 @@ typedef struct { unsigned int stopevent; } Button; +typedef struct { + char *token; + char *uri; +} SearchEngine; + typedef struct { const char *uri; Parameter config[ParameterLast]; @@ -207,15 +212,12 @@ static void decidenewwindow(WebKitPolicyDecision *d, Client *c); static void decideresource(WebKitPolicyDecision *d, Client *c); static void insecurecontent(WebKitWebView *v, WebKitInsecureContentEvent e, Client *c); -static void downloadstarted(WebKitWebContext *wc, WebKitDownload *d, - Client *c); -static void responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c); -static void download(Client *c, WebKitURIResponse *r); static void webprocessterminated(WebKitWebView *v, WebKitWebProcessTerminationReason r, Client *c); static void closeview(WebKitWebView *v, Client *c); static void destroywin(GtkWidget* w, Client *c); +static gchar *parseuri(const gchar *uri); /* Hotkeys */ static void pasteuri(GtkClipboard *clipboard, const char *text, gpointer d); @@ -239,6 +241,17 @@ static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h); static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h); static void clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h); +/* download-console */ +static void downloadstarted(WebKitWebContext *wc, WebKitDownload *d, + Client *c); +static void downloadfailed(WebKitDownload *d, GParamSpec *ps, void *arg); +static void downloadfinished(WebKitDownload *d, GParamSpec *ps, void *arg); +static gboolean decidedestination(WebKitDownload *d, + gchar *suggested_filename, void *arg); +static void printprogress(WebKitDownload *d, GParamSpec *ps, void *arg); +static void logdownload(WebKitDownload *d, gchar *tail); +static void spawndls(Client *c, const Arg *a); + static char winid[64]; static char togglestats[12]; static char pagestats[2]; @@ -350,7 +363,10 @@ setup(void) cookiefile = buildfile(cookiefile); scriptfile = buildfile(scriptfile); certdir = buildpath(certdir); - if (curconfig[Ephemeral].val.i) + dlstatus = buildpath(dlstatus); + dldir = buildpath(dldir); + + if (curconfig[Ephemeral].val.i) cachedir = NULL; else cachedir = buildpath(cachedir); @@ -576,7 +592,7 @@ loaduri(Client *c, const Arg *a) url = g_strdup_printf("file://%s", path); free(path); } else { - url = g_strdup_printf("http://%s", uri); + url = parseuri(uri); } if (apath != uri) free(apath); @@ -1088,6 +1104,8 @@ cleanup(void) g_free(scriptfile); g_free(stylefile); g_free(cachedir); + g_free(dldir); + g_free(dlstatus); XCloseDisplay(dpy); } @@ -1721,8 +1739,7 @@ decideresource(WebKitPolicyDecision *d, Client *c) if (webkit_response_policy_decision_is_mime_type_supported(r)) { webkit_policy_decision_use(d); } else { - webkit_policy_decision_ignore(d); - download(c, res); + webkit_policy_decision_download(d); } } @@ -1732,27 +1749,6 @@ insecurecontent(WebKitWebView *v, WebKitInsecureContentEvent e, Client *c) c->insecure = 1; } -void -downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c) -{ - g_signal_connect(G_OBJECT(d), "notify::response", - G_CALLBACK(responsereceived), c); -} - -void -responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c) -{ - download(c, webkit_download_get_response(d)); - webkit_download_cancel(d); -} - -void -download(Client *c, WebKitURIResponse *r) -{ - Arg a = (Arg)DOWNLOAD(webkit_uri_response_get_uri(r), geturi(c)); - spawn(c, &a); -} - void webprocessterminated(WebKitWebView *v, WebKitWebProcessTerminationReason r, Client *c) @@ -1776,6 +1772,20 @@ destroywin(GtkWidget* w, Client *c) gtk_main_quit(); } +gchar * +parseuri(const gchar *uri) +{ + guint i; + + for (i = 0; i < LENGTH(searchengines); i++) { + if (g_str_has_prefix(uri, searchengines[i].token)) + return g_strdup_printf(searchengines[i].uri, + uri + strlen(searchengines[i].token)); + } + + return g_strdup_printf("http://%s", uri); +} + void pasteuri(GtkClipboard *clipboard, const char *text, gpointer d) { @@ -1985,6 +1995,81 @@ clickexternplayer(Client *c, const Arg *a, WebKitHitTestResult *h) spawn(c, &arg); } +/* download-console */ + +void +downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c) +{ + webkit_download_set_allow_overwrite(d, TRUE); + g_signal_connect(G_OBJECT(d), "decide-destination", + G_CALLBACK(decidedestination), NULL); + g_signal_connect(G_OBJECT(d), "notify::estimated-progress", + G_CALLBACK(printprogress), NULL); + g_signal_connect(G_OBJECT(d), "failed", + G_CALLBACK(downloadfailed), NULL); + g_signal_connect(G_OBJECT(d), "finished", + G_CALLBACK(downloadfinished), NULL); +} + +void +downloadfailed(WebKitDownload *d, GParamSpec *ps, void *arg) +{ + logdownload(d, " -- FAILED"); +} + +void +downloadfinished(WebKitDownload *d, GParamSpec *ps, void *arg) +{ + logdownload(d, " -- COMPLETED"); +} + +gboolean +decidedestination(WebKitDownload *d, gchar *suggested_filename, void *arg) +{ + gchar *dest; + dest = g_strdup_printf("file://%s/%s", dldir, suggested_filename); + webkit_download_set_destination(d, dest); + return TRUE; +} + +void +printprogress(WebKitDownload *d, GParamSpec *ps, void *arg) +{ + logdownload(d, ""); +} + +void +logdownload(WebKitDownload *d, gchar *tail) +{ + gchar *filename, *statfile; + FILE *stat; + + filename = g_path_get_basename(webkit_download_get_destination(d)); + statfile = g_strdup_printf("%s/%s", dlstatus, filename); + + if ((stat = fopen(statfile, "w")) == NULL) { + perror("dlstatus"); + } else { + fprintf(stat, "%s: %d%% (%d.%ds)%s\n", + filename, + (int)(webkit_download_get_estimated_progress(d) * 100), + (int) webkit_download_get_elapsed_time(d), + (int)(webkit_download_get_elapsed_time(d) * 100), + tail); + fclose(stat); + } + + g_free(statfile); + g_free(filename); +} + +void +spawndls(Client *c, const Arg *a) +{ + Arg arg = (Arg)DLSTATUS; + spawn(c, &arg); +} + int main(int argc, char *argv[]) {