-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathtelnet.cl
71 lines (61 loc) · 2.57 KB
/
telnet.cl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
;; -*- mode: common-lisp -*-
;;
;; This source code is in the public domain.
(in-package :user)
(defun start-telnet-server (&key (port 1234))
(mp:process-run-function "telnet server" 'start-telnet-server-1 port))
(defun start-telnet-server-1 (port)
(loop
(let ((socket (socket:make-socket :connect :passive :local-port port
:reuse-address t)))
(unwind-protect
(loop
(let ((connection
(ignore-errors (socket:accept-connection socket)))
;; The ignore-errors protects against the rare
;; occurrence of accept-connection signaling
;; an error (usually Connection Reset by Peer)
from)
(when connection
(handler-case
(progn
(setq from (or (socket:ipaddr-to-hostname
(socket:remote-host connection))
(socket:ipaddr-to-dotted
(socket:remote-host connection))))
(logit-stamp "telnet server: new connection from ~a~%"
from)
(setf (eol-convention connection) :dos)
(format connection "
WARNING: do not use :exit or (exit). Use ~s to quit."
'(quit))
(force-output connection)
(mp:process-run-function
"telnet session"
'start-telnet-session connection from))
(error ()
(ignore-errors (close connection)))))))
(ignore-errors (close socket))))))
(defvar *in-telnet-session* nil)
(defun start-telnet-session (s from)
(unwind-protect
(catch 'end-telnet-session
(let ((*in-telnet-session* t))
(setq excl::*set-acl-running-mutex* nil)
(tpl:start-interactive-top-level
s 'tpl:top-level-read-eval-print-loop nil)))
(ignore-errors (close s)))
(logit-stamp "telnet server: closing connection from ~a~%" from))
(defun quit ()
(throw 'end-telnet-session nil))
(defvar *exit-wrapped* nil)
(when (not *exit-wrapped*)
(flet ((msg ()
(format t "Use ~s instead of exit.~%" '(quit))))
(def-fwrapper exit-wrapper (&optional status &rest args)
(declare (ignore args))
(if* *in-telnet-session*
then (msg)
else (call-next-fwrapper)))
(fwrap 'excl:exit :telnet-server 'exit-wrapper)
(fwrap 'tpl::exit-command :telnet-server 'exit-wrapper)))