changeset 698: |
96958d3eb5b0 |
parent: |
a304c9713a51
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 ;;; c2.el --- remote execution of elisp -*- lexical-binding: t -*- 2 ;; Copyright (C) 2021-2024 ellis 5 ;; Keywords: local, vc, net, process 7 ;; This program is free software; you can redistribute it and/or modify 8 ;; it under the terms of the GNU General Public License as published by 9 ;; the Free Software Foundation, either version 3 of the License, or 10 ;; (at your option) any later version. 12 ;; This program is distributed in the hope that it will be useful, 13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 ;; GNU General Public License for more details. 17 ;; You should have received a copy of the GNU General Public License 18 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 22 ;; This package provides functions for executing elisp on a running 23 ;; emacs instance remotely. 29 (defcustom c2-directory (join-paths user-stash-directory "c2") "c2 directory." 32 (defcustom c2-after-make-frame-hook nil 33 "Hook run when c2 creates a client frame. 34 The created frame is selected when the hook is called." 38 (defcustom c2-done-hook nil 39 "Hook run when done editing a buffer with c2." 43 (defcustom c2-port 62824 44 "port of the c2 broadcaster" 47 (defvar c2-process nil 48 "The c2 process handle.") 50 (defvar c2-clients nil 51 "List of current c2 clients. 52 Each element is a process.") 55 (setq c2-header-bindat-spec 61 (setq c2-body-bindat-spec 69 (setq c2-packet-bindat-spec 70 '((header struct header-spec) 77 (defun c2-insert-string (string) 78 (insert string 0 (make-string (- 3 (% (length string) 4)) 0))) 80 (defun c2-insert-int32 (value) 83 (push (% value 256) bytes) 84 (setq value (/ value 256))) 88 (defun c2-insert-float32 (value) 91 ((string= (format "%f" value) (format "%f" -0.0)) 93 ((string= (format "%f" value) (format "%f" 0.0)) 96 (setq s 0 e 255 f (1- (expt 2 23)))) 98 (setq s 1 e 255 f (1- (expt 2 23)))) 99 ((string= (format "%f" value) (format "%f" 0.0e+NaN)) 100 (setq s 0 e 255 f 1)) 102 (setq s (if (>= value 0.0) 103 (progn (setq f value) 0) 104 (setq f (* -1 value)) 1)) 105 (while (>= (* f (expt 2.0 e)) 2.0) (setq e (1- e))) 106 (if (= e 0) (while (< (* f (expt 2.0 e)) 1.0) (setq e (1+ e)))) 107 (setq f (round (* (1- (* f (expt 2.0 e))) (expt 2 23))) 108 e (+ (* -1 e) 127)))) 109 (insert (+ (lsh s 7) (lsh (logand e #XFE) -1)) 110 (+ (lsh (logand e #X01) 7) (lsh (logand f #X7F0000) -16)) 111 (lsh (logand f #XFF00) -8) 114 (defun c2-read-string () 115 (let ((pos (point)) string) 116 (while (not (= (following-char) 0)) (forward-char 1)) 117 (setq string (buffer-substring-no-properties pos (point))) 118 (forward-char (- 4 (% (length string) 4))) 121 (defun c2-read-int32 () 124 (setq value (logior (* value 256) (following-char))) 128 (defun c2-read-float32 () 129 (let ((s (lsh (logand (following-char) #X80) -7)) 130 (e (+ (lsh (logand (following-char) #X7F) 1) 131 (lsh (logand (progn (forward-char) (following-char)) #X80) -7))) 132 (f (+ (lsh (logand (following-char) #X7F) 16) 133 (lsh (progn (forward-char) (following-char)) 8) 134 (prog1 (progn (forward-char) (following-char)) (forward-char))))) 136 ((and (= e 0) (= f 0)) 138 ((and (= e 255) (or (= f (1- (expt 2 23))) (= f 0))) 139 (* 1.0e+INF (expt -1 s))) 140 ((and (= e 255) (not (or (= f 0) (= f (1- (expt 2 23)))))) 145 (1+ (/ f (expt 2.0 23))))))))) 149 (defun net-check-opts () 150 ;; https://gnu.huihoo.org/emacs/24.4/emacs-lisp/Network-Options.html#Network-Options 152 (featurep 'make-network-process '(:nowait t)) 154 ;(featurep 'make-network-process '(:family local)) 156 (featurep 'make-network-process '(:type datagram))) 159 (defun c2-make-client (host port) 160 (make-network-process 168 (defun c2-sentinel (proc msg) 169 (when (string= msg "connection broken by remote peer\n") 170 (setq c2-clients (assq-delete-all proc c2-clients)) 171 (c2-log (format "client %s has quit" proc)))) 174 (defun c2-log (string &optional client) 175 "If a *c2* buffer exists, write STRING to it for logging purposes." 176 (if (get-buffer "*c2*") 177 (with-current-buffer "*c2*" 178 (goto-char (point-max)) 179 (insert (if client (format "<%s>: " (format-network-address (process-datagram-address client)))) 181 (or (bolp) (newline))))) 187 (unless (process-status "c2") 188 (make-network-process :name "c2" 194 :sentinel 'c2-sentinel 198 (setq c2-clients '()) 199 ;; setup additional filters 200 (add-function :after (process-filter (get-process "c2")) #'c2-eval-response-filter)) 201 (message "c2: ONLINE")) 205 "stop the c2 server." 208 (delete-process (car (car c2-clients))) 209 (setq c2-clients (cdr c2-clients))) 210 (with-current-buffer "*c2*" 211 (let ((proc (get-buffer-process (current-buffer)))) 212 (if proc (delete-process proc))) 213 (set-buffer-modified-p nil) 215 (message "c2 stopped")) 217 (defun c2-filter (proc string) 218 (let ((pending (assoc proc c2-clients)) 221 ;;create entry if required 223 (setq c2-clients (cons (cons proc "") c2-clients)) 224 (setq pending (assoc proc c2-clients))) 225 (setq message (concat (cdr pending) string)) 226 (while (setq index (string-match "\n" message)) 227 (setq index (1+ index)) 228 ; (process-send-string proc (substring message 0 index)) 229 (c2-log (substring message 0 index) proc) 230 (setq message (substring message index))) 231 (setcdr pending message))) 233 (defun c2-packet-filter (proc string) 234 "process-filter for decoding 'c2-packet-bindat-spec'" 235 (bindat-unpack packet-spec string)) 237 (defun ordinary-insertion-filter (proc string) 238 (when (buffer-live-p (process-buffer proc)) 239 (with-current-buffer (process-buffer proc) 240 (let ((moving (= (point) (process-mark proc)))) 243 ;; Insert the text, advancing the process marker. 244 (goto-char (process-mark proc)) 246 (set-marker (process-mark proc) (point))) 247 (if moving (goto-char (process-mark proc))))))) 249 (defun c2-eval-response-filter (proc string) 250 "execute STRING from PROC." 251 (let ((msg (car (read-from-string string)))) 252 (process-send-string proc (concat (format "%s" (ignore-errors "error: %S" (eval msg))) "\n")))) 256 (defun c2-shutdown () 257 "Save buffers, Quit, and Shutdown (kill) server" 264 "Handler for SIGUSR1 signal, to (re)start an emacs server. 266 Can be tested from within emacs with: 267 (signal-process (emacs-pid) 'sigusr1) 269 or from the command line with: 270 $ kill -USR1 <emacs-pid> 274 (server-force-delete) 278 (define-key special-event-map [sigusr1] 'c2-restart)