💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › beaf33eaf2b21b3957c28457efd45… captured on 2023-04-19 at 23:08:00. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 /* See LICENSE file for copyright and license details. */
1 #include <sys/wait.h>
2 #ifdef __linux__
3 #include <sys/prctl.h>
4 #endif
5 #ifndef NO_SANDBOX
6 #ifdef sun
7 #include <priv.h>
8 int init_privs(const char **privs);
9 #endif
10 #endif
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include "cert.h"
17 #include "str.h"
18
19 const char startby[] = "XDG_DOWNLOAD_DIR=\"$HOME";
20
21 #ifndef DISABLE_XDG
22 #if defined(__FreeBSD__) || defined(__OpenBSD__) || \
23 defined(__linux__) || defined(sun)
24
25 int xdg_pipe[2] = {-1, -1};
26 int xdg_open(const char*);
27
28 int xdg_request(char* str) {
29 int len = strnlen(str, 1024)+1;
30 return write(xdg_pipe[1], str, len) != len;
31 }
32
33 void xdg_listener() {
34 char buf[4096];
35 while (1) {
36 int len = read(xdg_pipe[0], buf, sizeof(buf));
37 if (len <= 0)
38 break;
39 xdg_open(buf);
40 }
41 }
42
43 int xdg_init() {
44 if (gethomefd() < 0) {
45 return -1;
46 }
47
48 if (pipe(xdg_pipe)) {
49 printf("pipe failed\n");
50 return -1;
51 }
52 int pid = fork();
53 if (pid != 0) {
54 close(xdg_pipe[0]);
55 return 0;
56 }
57 close(xdg_pipe[1]);
58
59 chdir(download_path);
60
61 #ifndef NO_SANDBOX
62 #ifdef __OpenBSD__
63 if (unveil("/bin/sh", "x") ||
64 unveil("/usr/bin/which", "x") ||
65 unveil("/usr/local/bin/xdg-open", "x") ||
66 unveil(NULL, NULL)) {
67 close(xdg_pipe[1]);
68 exit(-1);
69 }
70 if (pledge("stdio rpath exec proc", NULL)) {
71 close(xdg_pipe[1]);
72 exit(-1);
73 }
74 #endif
75 #ifdef sun
76 const char* privs[] = {PRIV_PROC_FORK, PRIV_PROC_EXEC,
77 PRIV_FILE_READ, PRIV_FILE_WRITE, NULL};
78 if (init_privs(privs)) {
79 exit(-1);
80 }
81 #endif
82 #endif
83
84 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
85 setproctitle("vgmi.xdg");
86 #endif
87 #ifdef __linux__
88 prctl(PR_SET_NAME, "vgmi [xdg]", 0, 0, 0);
89 #endif
90 xdg_listener();
91 exit(0);
92 }
93
94 void xdg_close() {
95 if (xdg_pipe[0] > -1)
96 close(xdg_pipe[0]);
97 if (xdg_pipe[1] > -1)
98 close(xdg_pipe[1]);
99 }
100
101 #endif
102 #endif
103
104 #define SB_IGNORE
105 #include "gemini.h"
106 int xdg_open(const char* str) {
107 if (!client.xdg) return 0;
108 char buf[4096];
109 snprintf(buf, sizeof(buf), "xdg-open %s>/dev/null 2>&1", str);
110 if (fork() == 0) {
111 setsid();
112 char* argv[] = {"/bin/sh", "-c", buf, NULL};
113 execvp(argv[0], argv);
114 exit(0);
115 }
116 return 0;
117 }
118
119 int xdg_path(char* path, size_t len) {
120 int home = gethomefd();
121 if (home < 0) return -1;
122 int fd = openat(home, ".config/user-dirs.dirs", O_RDONLY);
123 if (fd < 0) return -1;
124 char line[1024];
125 int found = -1;
126 for (size_t i = 0; found; i++) {
127 if (i >= sizeof(line)) break;
128 if (read(fd, &line[i], 1) != 1) break;
129 if (line[i] != '\n') continue;
130 line[i] = '\0';
131 if (sizeof(startby) >= i ||
132 strncmp(line, startby, sizeof(startby) - 1)) {
133 i = -1;
134 continue;
135 }
136 int offset = strlcpy(path, home_path, len);
137 for (size_t j = 0; j < len - 1; j++) {
138 path[offset + j] = line[sizeof(startby) - 1 + j];
139 if (path[offset + j] == '"') {
140 found = 0;
141 path[offset + j] = 0;
142 break;
143 }
144 }
145 }
146 close(fd);
147 return found;
148 }
149