Bash is modified to call out to Guile code whenever the user enters a command-line; the code has the opportunity to fix up the command line in any way. The Guile code is under the ibash-scheme directory, all is all newly created in this delta. * configure: why does this have to be in here? * configure.ac: look for guile and libguile. * eval.c: call guile_main and load ~/.bash_guile.scm. * shell.c: perform call-outs prior to executing command lines. * ibash-scheme/ibash-callout.scm: first call-out. * ibash-scheme/remote-sender.scm: second call-out. * ibash-scheme/ibash-server.scm: central intelligence service. * ibash-scheme/modules/i-bash: transform ib -> i-bash. * ibash-scheme/modules/cd: cd command line processor.
94 lines
4 KiB
Scheme
94 lines
4 KiB
Scheme
;; THE FULL PATH TO THIS FILE SHOULD BE REFERRED TO IN THE ENVIRONMENT
|
|
;; VARIABLE "I_BASH_CALLOUT_2", OR ELSE COPIED TO
|
|
;; "$HOME/i-bash/remote-sender.scm", FOR EFFECT.
|
|
|
|
|
|
;; The functions in this file are called-out to whenever the user enters
|
|
;; a command on the ibash command line.
|
|
|
|
|
|
;; Copyright (C) 2020 Dale Mellor
|
|
;;
|
|
;; This file is part of iBash, the intelligent Bourne Again SHell.
|
|
;;
|
|
;; iBash is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
;;
|
|
;; iBash is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
;;
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with iBash. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
(define-module (db core)
|
|
#:use-module (ice-9 popen)
|
|
#:export (process))
|
|
|
|
|
|
;; Either return (cons socket action-procedure) or #f.
|
|
(define (establish-remote-call)
|
|
(let ((connection (getenv "I_BASH_REMOTE")))
|
|
(and connection
|
|
(let ((split (string-split connection #\:)))
|
|
(cond ((null? (cdr split)) #f)
|
|
(else
|
|
(catch 'getaddrinfo-error
|
|
(lambda ()
|
|
(let* ((addr (car (getaddrinfo (car split)
|
|
(cadr split) 0 AF_INET)))
|
|
(socket (socket (addrinfo:fam addr)
|
|
(addrinfo:socktype addr)
|
|
(addrinfo:protocol addr))))
|
|
(connect socket (addrinfo:addr addr))
|
|
(cons socket
|
|
(lambda (command-words command-stack)
|
|
(write (cons command-words command-stack)
|
|
socket)
|
|
(let ((return (read socket)))
|
|
(and (not (null? return))
|
|
(eval return (current-module))))))))
|
|
(lambda (key errcode) #f))))))))
|
|
|
|
|
|
|
|
;; The command-words are the tokens of the command line (list of
|
|
;; strings), and the command-stack is a list of command lines *in reverse
|
|
;; order* which are derived by the intelligence from the originals
|
|
;; (command-words).
|
|
;;
|
|
;; The return value is the updated command-stack, this being ultimately
|
|
;; sent back to the bash program and executed as if the new commands had
|
|
;; been typed at the terminal.
|
|
(define (process command-words command-stack)
|
|
(cond ((establish-remote-call)
|
|
=> (lambda (R)
|
|
(let ((server-socket (car R))
|
|
(remote-call (cdr R))
|
|
(run-command (lambda (command)
|
|
(and command
|
|
(let ((ret (command command-words
|
|
command-stack)))
|
|
(when ret
|
|
(set! command-words (car ret))
|
|
(set! command-stack (cdr ret)))
|
|
ret)))))
|
|
(let loop ()
|
|
(unless (null? command-words)
|
|
(when (run-command (remote-call command-words
|
|
command-stack))
|
|
(loop))))
|
|
(when server-socket (close server-socket)))))
|
|
(else
|
|
(set! command-words
|
|
(string-split
|
|
"echo REMOTE iBASH INTELLIGENCE SERVICE NOT AVAILABLE"
|
|
#\space))))
|
|
(if (null? command-words)
|
|
command-stack
|
|
(cons command-words command-stack)))
|