1: ; -*- lexical-binding: t -*-
2: ;
3: ; syd.el --- Emacs Lisp implementation of the syd stat interface
4: ;
5: ; syd: seccomp and landlock based application sandbox with support for namespaces
6: ; lib/src/syd.el: Emacs Lisp implementation of the syd stat interface
7: ;
8: ; Copyright (c) 2023, 2024 Ali Polatel <alip@chesswob.org>
9: ;
10: ; SPDX-License-Identifier: GPL-3.0-or-later
11:
12: (defun syd-info ()
13: "Reads the state of the syd sandbox from /dev/syd and returns it as an alist.
14: If the `json' module is not available, returns nil."
15: (if (require 'json nil t)
16: (condition-case nil
17: (with-temp-buffer
18: (insert-file-contents "/dev/syd")
19: (with-no-warnings
20: (let ((json-object-type 'alist)
21: (json-array-type 'list)
22: (json-key-type 'symbol)
23: (json-false nil)
24: (json-null nil))
25: (json-read))))
26: (file-error
27: (message "Error reading /dev/syd.")
28: nil)
29: (json-error
30: (message "JSON decoding error.")
31: nil))
32: (progn
33: (message "JSON module not available.")
34: nil)))
35:
36: (defun syd-api ()
37: "Performs a syd API check."
38: (if (syd--stat "/dev/syd/3")
39: 3 ; API number on success
40: nil)) ; On error, return nil
41:
42: (defun syd-check ()
43: "Check if '/dev/syd' is a character device."
44: (syd--stat "/dev/syd"))
45:
46: (defun syd-panic ()
47: "Causes syd to exit immediately with code 127"
48: (syd--stat "/dev/syd/panic"))
49:
50: (defun syd-reset ()
51: "Causes syd to reset sandboxing to the default state."
52: (syd--stat "/dev/syd/reset"))
53:
54: (defun syd-load (fd)
55: "Causes syd to read configuration from the given file descriptor FD."
56: (let ((path (concat "/dev/syd/load/" (number-to-string fd))))
57: (syd--stat path)))
58:
59: ; Define lock states as keywords
60: (defconst syd-lock-off :lock-off
61: "The sandbox lock is off, allowing all sandbox commands.")
62:
63: (defconst syd-lock-exec :lock-exec
64: "The sandbox lock is set to on for all processes except the initial process
65: \(syd exec child). This is the default state.")
66:
67: (defconst syd-lock-on :lock-on
68: "The sandbox lock is on, disallowing all sandbox commands.")
69:
70: (defun syd-lock (state)
71: "Sets the state of the sandbox lock.
72: STATE is one of the keywords :lock-off, :lock-exec, or :lock-on.
73: Returns t on success, nil on failure."
74: (cond
75: ((eq state syd-lock-off) (syd--stat "/dev/syd/lock:off"))
76: ((eq state syd-lock-exec) (syd--stat "/dev/syd/lock:exec"))
77: ((eq state syd-lock-on) (syd--stat "/dev/syd/lock:on"))
78: (t nil))) ; Invalid state
79:
80: (defun syd-enabled-mem ()
81: "Checks if memory sandboxing is enabled."
82: (syd--stat "/dev/syd/sandbox/mem?"))
83:
84: (defun syd-enable-mem ()
85: "Enable memory sandboxing."
86: (syd--stat "/dev/syd/sandbox/mem:on"))
87:
88: (defun syd-disable-mem ()
89: "Disable memory sandboxing."
90: (syd--stat "/dev/syd/sandbox/mem:off"))
91:
92: (defun syd-enabled-pid ()
93: "Checks if PID sandboxing is enabled."
94: (syd--stat "/dev/syd/sandbox/pid?"))
95:
96: (defun syd-enable-pid ()
97: "Enable PID sandboxing."
98: (syd--stat "/dev/syd/sandbox/pid:on"))
99:
100: (defun syd-disable-pid ()
101: "Disable PID sandboxing."
102: (syd--stat "/dev/syd/sandbox/pid:off"))
103:
104: (defun syd-enabled-read ()
105: "Checks if Read sandboxing is enabled."
106: (syd--stat "/dev/syd/sandbox/read?"))
107:
108: (defun syd-enable-read ()
109: "Enable Read sandboxing."
110: (syd--stat "/dev/syd/sandbox/read:on"))
111:
112: (defun syd-disable-read ()
113: "Disable Read sandboxing."
114: (syd--stat "/dev/syd/sandbox/read:off"))
115:
116: (defun syd-enabled-stat ()
117: "Checks if Stat sandboxing is enabled."
118: (syd--stat "/dev/syd/sandbox/stat?"))
119:
120: (defun syd-enable-stat ()
121: "Enable Stat sandboxing."
122: (syd--stat "/dev/syd/sandbox/stat:on"))
123:
124: (defun syd-disable-stat ()
125: "Disable Stat sandboxing."
126: (syd--stat "/dev/syd/sandbox/stat:off"))
127:
128: (defun syd-enabled-write ()
129: "Checks if Write sandboxing is enabled."
130: (syd--stat "/dev/syd/sandbox/write?"))
131:
132: (defun syd-enable-write ()
133: "Enable Write sandboxing."
134: (syd--stat "/dev/syd/sandbox/write:on"))
135:
136: (defun syd-disable-write ()
137: "Disable Write sandboxing."
138: (syd--stat "/dev/syd/sandbox/write:off"))
139:
140: (defun syd-enabled-exec ()
141: "Checks if Exec sandboxing is enabled."
142: (syd--stat "/dev/syd/sandbox/exec?"))
143:
144: (defun syd-enable-exec ()
145: "Enable Exec sandboxing."
146: (syd--stat "/dev/syd/sandbox/exec:on"))
147:
148: (defun syd-disable-exec ()
149: "Disable Exec sandboxing."
150: (syd--stat "/dev/syd/sandbox/exec:off"))
151:
152: (defun syd-enabled-force ()
153: "Checks if force sandboxing is enabled."
154: (syd--stat "/dev/syd/sandbox/force?"))
155:
156: (defun syd-enable-force ()
157: "Enable force sandboxing."
158: (syd--stat "/dev/syd/sandbox/force:on"))
159:
160: (defun syd-disable-force ()
161: "Disable force sandboxing."
162: (syd--stat "/dev/syd/sandbox/force:off"))
163:
164: (defun syd-enabled-net ()
165: "Checks if Network sandboxing is enabled."
166: (syd--stat "/dev/syd/sandbox/net?"))
167:
168: (defun syd-enable-net ()
169: "Enable Network sandboxing."
170: (syd--stat "/dev/syd/sandbox/net:on"))
171:
172: (defun syd-disable-net ()
173: "Disable Network sandboxing."
174: (syd--stat "/dev/syd/sandbox/net:off"))
175:
176: (defun syd-kill-add (glob)
177: "Adds to the list of glob patterns to kill in the sandbox.
178: GLOB is a string representing the glob pattern."
179: (syd--stat (syd--rule "exec/kill" glob ?+)))
180:
181: (defun syd-kill-del (glob)
182: "Deletes the first matching item from the end of the list of glob patterns
183: to kill in the sandbox.
184: GLOB is a string representing the glob pattern."
185: (syd--stat (syd--rule "exec/kill" glob ?-)))
186:
187: (defun syd-kill-rem (glob)
188: "Removes all matching items from the list of glob patterns
189: to kill in the sandbox.
190: GLOB is a string representing the glob pattern."
191: (syd--stat (syd--rule "exec/kill" glob ?^)))
192:
193: ; Define force actions as keywords
194: (defconst syd-force-action-allow :force-allow
195: "Allow system call.")
196:
197: (defconst syd-force-action-warn :force-warn
198: "Print a warning to syslog.")
199:
200: (defconst syd-force-action-deny :force-deny
201: "Deny system call with EACCES")
202:
203: (defconst syd-force-action-kill :force-kill
204: "Kill process with SIGKILL.")
205:
206: (defun syd-force-add (path hash action)
207: "Adds an entry to the Integrity Force map for Force Sandboxing.
208: PATH is a fully-qualified file name.
209: HASH is a hexadecimal encoded checksum.
210: ACTION is one of :force-warn, :force-deny or :force-kill."
211: (let ((action (cond ((eq action :force-warn) "warn")
212: ((eq action :force-deny) "deny")
213: ((eq action :force-kill) "kill"))))
214: ; Only proceed if action is not nil
215: (when action
216: ; Create the command string
217: (let ((cmd (format "/dev/syd/force+%s:%s:%s" path hash action)))
218: ; Call syd--stat with the command
219: (syd--stat cmd)))))
220:
221: (defun syd-force-del (path)
222: "Removes an entry from the Integrity Force map for Force Sandboxing.
223: PATH is a fully-qualified file name."
224: ; Create the command string
225: (let ((cmd (format "/dev/syd/force-%s" path)))
226: ; Call syd--stat with the command
227: (syd--stat cmd)))
228:
229: (defun syd-force-clr ()
230: "Clears the Integrity Force map for Force Sandboxing."
231: (syd--stat "/dev/syd/force^"))
232:
233: (defun syd-force-def (action)
234: "Set the default action for Force Sandboxing.
235: ACTION is one of :force-allow, :force-warn, :force-deny or :force-kill."
236: (let ((action (cond ((eq action :force-allow) "allow")
237: ((eq action :force-warn) "warn")
238: ((eq action :force-deny) "deny")
239: ((eq action :force-kill) "kill"))))
240: ; Only proceed if action is not nil
241: (when action
242: ; Create the command string
243: (let ((cmd (format "/dev/syd/force/default:%s" action)))
244: ; Call syd--stat with the command
245: (syd--stat cmd)))))
246:
247: (defun syd-allow-read-add (glob)
248: "Adds to the allowlist of read sandboxing.
249: GLOB is a string representing the glob pattern."
250: (syd--stat (syd--rule "allow/read" glob ?+)))
251:
252: (defun syd-allow-read-del (glob)
253: "Removes the first instance from the end of the allowlist of read sandboxing.
254: GLOB is a string representing the glob pattern."
255: (syd--stat (syd--rule "allow/read" glob ?-)))
256:
257: (defun syd-allow-read-rem (glob)
258: "Removes all matching items from the list of glob patterns
259: to allow-read in the sandbox.
260: GLOB is a string representing the glob pattern."
261: (syd--stat (syd--rule "allow/read" glob ?^)))
262:
263: (defun syd-deny-read-add (glob)
264: "Adds to the denylist of read sandboxing.
265: GLOB is a string representing the glob pattern."
266: (syd--stat (syd--rule "deny/read" glob ?+)))
267:
268: (defun syd-deny-read-del (glob)
269: "Removes the first instance from the end of the denylist of read sandboxing.
270: GLOB is a string representing the glob pattern."
271: (syd--stat (syd--rule "deny/read" glob ?-)))
272:
273: (defun syd-deny-read-rem (glob)
274: "Removes all matching items from the list of glob patterns
275: to deny-read in the sandbox.
276: GLOB is a string representing the glob pattern."
277: (syd--stat (syd--rule "deny/read" glob ?^)))
278:
279: (defun syd-filter-read-add (glob)
280: "Adds to the filter of read sandboxing.
281: GLOB is a string representing the glob pattern."
282: (syd--stat (syd--rule "filter/read" glob ?+)))
283:
284: (defun syd-filter-read-del (glob)
285: "Removes the first instance from the end of the filter of read sandboxing.
286: GLOB is a string representing the glob pattern."
287: (syd--stat (syd--rule "filter/read" glob ?-)))
288:
289: (defun syd-filter-read-rem (glob)
290: "Removes all matching items from the list of glob patterns
291: to filter-read in the sandbox.
292: GLOB is a string representing the glob pattern."
293: (syd--stat (syd--rule "filter/read" glob ?^)))
294:
295: (defun syd-allow-stat-add (glob)
296: "Adds to the allowlist of stat sandboxing.
297: GLOB is a string representing the glob pattern."
298: (syd--stat (syd--rule "allow/stat" glob ?+)))
299:
300: (defun syd-allow-stat-del (glob)
301: "Removes the first instance from the end of the allowlist of stat sandboxing.
302: GLOB is a string representing the glob pattern."
303: (syd--stat (syd--rule "allow/stat" glob ?-)))
304:
305: (defun syd-allow-stat-rem (glob)
306: "Removes all matching items from the list of glob patterns
307: to allow-stat in the sandbox.
308: GLOB is a string representing the glob pattern."
309: (syd--stat (syd--rule "allow/stat" glob ?^)))
310:
311: (defun syd-deny-stat-add (glob)
312: "Adds to the denylist of stat sandboxing.
313: GLOB is a string representing the glob pattern."
314: (syd--stat (syd--rule "deny/stat" glob ?+)))
315:
316: (defun syd-deny-stat-del (glob)
317: "Removes the first instance from the end of the denylist of stat sandboxing.
318: GLOB is a string representing the glob pattern."
319: (syd--stat (syd--rule "deny/stat" glob ?-)))
320:
321: (defun syd-deny-stat-rem (glob)
322: "Removes all matching items from the list of glob patterns
323: to deny-stat in the sandbox.
324: GLOB is a string representing the glob pattern."
325: (syd--stat (syd--rule "deny/stat" glob ?^)))
326:
327: (defun syd-filter-stat-add (glob)
328: "Adds to the filter of stat sandboxing.
329: GLOB is a string representing the glob pattern."
330: (syd--stat (syd--rule "filter/stat" glob ?+)))
331:
332: (defun syd-filter-stat-del (glob)
333: "Removes the first instance from the end of the filter of stat sandboxing.
334: GLOB is a string representing the glob pattern."
335: (syd--stat (syd--rule "filter/stat" glob ?-)))
336:
337: (defun syd-filter-stat-rem (glob)
338: "Removes all matching items from the list of glob patterns
339: to filter-stat in the sandbox.
340: GLOB is a string representing the glob pattern."
341: (syd--stat (syd--rule "filter/stat" glob ?^)))
342:
343: (defun syd-allow-write-add (glob)
344: "Adds to the allowlist of write sandboxing.
345: GLOB is a string representing the glob pattern."
346: (syd--stat (syd--rule "allow/write" glob ?+)))
347:
348: (defun syd-allow-write-del (glob)
349: "Removes the first instance from the end of the allowlist of write sandboxing.
350: GLOB is a string representing the glob pattern."
351: (syd--stat (syd--rule "allow/write" glob ?-)))
352:
353: (defun syd-allow-write-rem (glob)
354: "Removes all matching items from the list of glob patterns
355: to allow-write in the sandbox.
356: GLOB is a string representing the glob pattern."
357: (syd--stat (syd--rule "allow/write" glob ?^)))
358:
359: (defun syd-deny-write-add (glob)
360: "Adds to the denylist of write sandboxing.
361: GLOB is a string representing the glob pattern."
362: (syd--stat (syd--rule "deny/write" glob ?+)))
363:
364: (defun syd-deny-write-del (glob)
365: "Removes the first instance from the end of the denylist of write sandboxing.
366: GLOB is a string representing the glob pattern."
367: (syd--stat (syd--rule "deny/write" glob ?-)))
368:
369: (defun syd-deny-write-rem (glob)
370: "Removes all matching items from the list of glob patterns
371: to deny-write in the sandbox.
372: GLOB is a string representing the glob pattern."
373: (syd--stat (syd--rule "deny/write" glob ?^)))
374:
375: (defun syd-filter-write-add (glob)
376: "Adds to the filter of write sandboxing.
377: GLOB is a string representing the glob pattern."
378: (syd--stat (syd--rule "filter/write" glob ?+)))
379:
380: (defun syd-filter-write-del (glob)
381: "Removes the first instance from the end of the filter of write sandboxing.
382: GLOB is a string representing the glob pattern."
383: (syd--stat (syd--rule "filter/write" glob ?-)))
384:
385: (defun syd-filter-write-rem (glob)
386: "Removes all matching items from the list of glob patterns
387: to filter-write in the sandbox.
388: GLOB is a string representing the glob pattern."
389: (syd--stat (syd--rule "filter/write" glob ?^)))
390:
391: (defun syd-allow-exec-add (glob)
392: "Adds to the allowlist of exec sandboxing.
393: GLOB is a string representing the glob pattern."
394: (syd--stat (syd--rule "allow/exec" glob ?+)))
395:
396: (defun syd-allow-exec-del (glob)
397: "Removes the first instance from the end of the allowlist of exec sandboxing.
398: GLOB is a string representing the glob pattern."
399: (syd--stat (syd--rule "allow/exec" glob ?-)))
400:
401: (defun syd-allow-exec-rem (glob)
402: "Removes all matching items from the list of glob patterns
403: to allow-exec in the sandbox.
404: GLOB is a string representing the glob pattern."
405: (syd--stat (syd--rule "allow/exec" glob ?^)))
406:
407: (defun syd-deny-exec-add (glob)
408: "Adds to the denylist of exec sandboxing.
409: GLOB is a string representing the glob pattern."
410: (syd--stat (syd--rule "deny/exec" glob ?+)))
411:
412: (defun syd-deny-exec-del (glob)
413: "Removes the first instance from the end of the denylist of exec sandboxing.
414: GLOB is a string representing the glob pattern."
415: (syd--stat (syd--rule "deny/exec" glob ?-)))
416:
417: (defun syd-deny-exec-rem (glob)
418: "Removes all matching items from the list of glob patterns
419: to deny-exec in the sandbox.
420: GLOB is a string representing the glob pattern."
421: (syd--stat (syd--rule "deny/exec" glob ?^)))
422:
423: (defun syd-filter-exec-add (glob)
424: "Adds to the filter of exec sandboxing.
425: GLOB is a string representing the glob pattern."
426: (syd--stat (syd--rule "filter/exec" glob ?+)))
427:
428: (defun syd-filter-exec-del (glob)
429: "Removes the first instance from the end of the filter of exec sandboxing.
430: GLOB is a string representing the glob pattern."
431: (syd--stat (syd--rule "filter/exec" glob ?-)))
432:
433: (defun syd-filter-exec-rem (glob)
434: "Removes all matching items from the list of glob patterns
435: to filter-exec in the sandbox.
436: GLOB is a string representing the glob pattern."
437: (syd--stat (syd--rule "filter/exec" glob ?^)))
438:
439: (defun syd-allow-net-bind-add (addr)
440: "Adds to the allowlist of net/bind sandboxing.
441: ADDR is a string representing the address pattern."
442: (syd--stat (syd--rule "allow/net/bind" addr ?+)))
443:
444: (defun syd-allow-net-bind-del (addr)
445: "Removes the first instance from the end of the allowlist of net/bind sandboxing.
446: ADDR is a string representing the address pattern."
447: (syd--stat (syd--rule "allow/net/bind" addr ?-)))
448:
449: (defun syd-allow-net-bind-rem (addr)
450: "Removes all matching items from the list of address patterns
451: to allow for net/bind in the sandbox.
452: ADDR is a string representing the address pattern."
453: (syd--stat (syd--rule "allow/net/bind" addr ?^)))
454:
455: (defun syd-deny-net-bind-add (addr)
456: "Adds to the denylist of net/bind sandboxing.
457: ADDR is a string representing the address pattern."
458: (syd--stat (syd--rule "deny/net/bind" addr ?+)))
459:
460: (defun syd-deny-net-bind-del (addr)
461: "Removes the first instance from the end of the denylist of net/bind sandboxing.
462: ADDR is a string representing the address pattern."
463: (syd--stat (syd--rule "deny/net/bind" addr ?-)))
464:
465: (defun syd-deny-net-bind-rem (addr)
466: "Removes all matching items from the list of address patterns
467: to deny for net/bind in the sandbox.
468: ADDR is a string representing the address pattern."
469: (syd--stat (syd--rule "deny/net/bind" addr ?^)))
470:
471: (defun syd-filter-net-bind-add (addr)
472: "Adds to the filter of net/bind sandboxing.
473: ADDR is a string representing the address pattern."
474: (syd--stat (syd--rule "filter/net/bind" addr ?+)))
475:
476: (defun syd-filter-net-bind-del (addr)
477: "Removes the first instance from the end of the filter of net/bind sandboxing.
478: ADDR is a string representing the address pattern."
479: (syd--stat (syd--rule "filter/net/bind" addr ?-)))
480:
481: (defun syd-filter-net-bind-rem (addr)
482: "Removes all matching items from the list of address patterns
483: to filter for net/bind in the sandbox.
484: ADDR is a string representing the address pattern."
485: (syd--stat (syd--rule "filter/net/bind" addr ?^)))
486:
487: (defun syd-allow-net-connect-add (addr)
488: "Adds to the allowlist of net/connect sandboxing.
489: ADDR is a string representing the address pattern."
490: (syd--stat (syd--rule "allow/net/connect" addr ?+)))
491:
492: (defun syd-allow-net-connect-del (addr)
493: "Removes the first instance from the end of the allowlist
494: of net/connect sandboxing.
495: ADDR is a string representing the address pattern."
496: (syd--stat (syd--rule "allow/net/connect" addr ?-)))
497:
498: (defun syd-allow-net-connect-rem (addr)
499: "Removes all matching items from the list of address patterns
500: to allow for net/connect in the sandbox.
501: ADDR is a string representing the address pattern."
502: (syd--stat (syd--rule "allow/net/connect" addr ?^)))
503:
504: (defun syd-deny-net-connect-add (addr)
505: "Adds to the denylist of net/connect sandboxing.
506: ADDR is a string representing the address pattern."
507: (syd--stat (syd--rule "deny/net/connect" addr ?+)))
508:
509: (defun syd-deny-net-connect-del (addr)
510: "Removes the first instance from the end of the denylist
511: of net/connect sandboxing.
512: ADDR is a string representing the address pattern."
513: (syd--stat (syd--rule "deny/net/connect" addr ?-)))
514:
515: (defun syd-deny-net-connect-rem (addr)
516: "Removes all matching items from the list of address patterns
517: to deny for net/connect in the sandbox.
518: ADDR is a string representing the address pattern."
519: (syd--stat (syd--rule "deny/net/connect" addr ?^)))
520:
521: (defun syd-filter-net-connect-add (addr)
522: "Adds to the filter of net/connect sandboxing.
523: ADDR is a string representing the address pattern."
524: (syd--stat (syd--rule "filter/net/connect" addr ?+)))
525:
526: (defun syd-filter-net-connect-del (addr)
527: "Removes the first instance from the end of the filter
528: of net/connect sandboxing.
529: ADDR is a string representing the address pattern."
530: (syd--stat (syd--rule "filter/net/connect" addr ?-)))
531:
532: (defun syd-filter-net-connect-rem (addr)
533: "Removes all matching items from the list of address patterns
534: to filter for net/connect in the sandbox.
535: ADDR is a string representing the address pattern."
536: (syd--stat (syd--rule "filter/net/connect" addr ?^)))
537:
538: (defun syd-mem-max (size)
539: "Set syd maximum per-process memory usage limit.
540: SIZE can be an integer or a string representing the memory limit."
541: (let ((size-str (cond ((integerp size) (number-to-string size))
542: ((stringp size) size)
543: (t (error "Size must be an integer or a string")))))
544: (syd--stat (syd--rule "mem/max" size-str ?:))))
545:
546: (defun syd-mem-vm-max (size)
547: "Set syd maximum per-process virtual memory usage limit.
548: SIZE can be an integer or a string representing the memory limit."
549: (let ((size-str (cond ((integerp size) (number-to-string size))
550: ((stringp size) size)
551: (t (error "Size must be an integer or a string")))))
552: (syd--stat (syd--rule "mem/vm_max" size-str ?:))))
553:
554: (defun syd-pid-max (size)
555: "Set syd maximum process ID limit for PID sandboxing.
556: SIZE is a number representing the PID limit."
557: (unless (numberp size)
558: (error "Size must be a number"))
559: (let ((path (format "/dev/syd/pid/max:%d" size)))
560: (syd--stat path)))
561:
562: (defun syd-filter-mem (state)
563: "Toggles the reporting of access violations for memory sandboxing.
564: STATE is a boolean representing the state of the filter."
565: (let ((path (if state "/dev/syd/filter/mem:1" "/dev/syd/filter/mem:0")))
566: (syd--stat path)))
567:
568: (defun syd-filter-pid (state)
569: "Toggles the reporting of access violations for PID sandboxing.
570: STATE is a boolean representing the state of the filter."
571: (let ((path (if state "/dev/syd/filter/pid:1" "/dev/syd/filter/pid:0")))
572: (syd--stat path)))
573:
574: (defun syd-kill-mem (state)
575: "Toggle kill of the offending process for Memory sandboxing.
576: STATE is a boolean representing the state of the option."
577: (let ((path (if state "/dev/syd/mem/kill:1" "/dev/syd/mem/kill:0")))
578: (syd--stat path)))
579:
580: (defun syd-kill-pid (state)
581: "Toggle kill of the offending process for PID sandboxing.
582: STATE is a boolean representing the state of the option."
583: (let ((path (if state "/dev/syd/pid/kill:1" "/dev/syd/pid/kill:0")))
584: (syd--stat path)))
585:
586: (defun syd-exec (file argv)
587: "Execute a command outside the sandbox without sandboxing.
588: FILE is the file path of the command as a string.
589: ARGV is a list of strings representing the arguments to the command."
590: (unless (stringp file)
591: (error "File must be a string"))
592: (let ((all-strings t))
593: (dolist (arg argv)
594: (unless (stringp arg)
595: (setq all-strings nil)))
596: (unless all-strings
597: (error "All elements in ARGV must be strings")))
598:
599: (let ((cmd (mapconcat 'identity (cons file argv) "\x1F")))
600: (syd--stat (concat "/dev/syd/cmd/exec!" cmd))))
601:
602: (defun syd--rule (rule elem op)
603: "Helper function to construct a path for syd operations.
604: RULE is a string representing the rule.
605: ELEM is a string representing the element.
606: OP is a character representing the operation."
607: (unless (member op '(?+ ?- ?^ ?:))
608: (error "Invalid operation"))
609: (when (string-empty-p elem)
610: (error "Element cannot be empty"))
611: (concat "/dev/syd/" rule (char-to-string op) elem))
612:
613: (defun syd--stat (path)
614: "Check if the file at PATH exists using `file-modes'."
615: (condition-case nil
616: (not (null (file-modes path)))
617: (error nil))) ; On error, return nil
618:
619: (provide 'syd)
620: ; syd.el ends here
621:
04/03/2024 20:46:17, src/syd.el, Ali Polatel