echo Impossible|sed 's/Im/To be /'

December 28, 2017

List ip address of G suite

早先用 emacs lisp 寫了一段 code 列出 G suite 所有的 ip address ,但因斷電後 code 找不到了。改用 CL 重寫後留個記錄方便查詢。另一個心得就是 CL :inferior-shell 很好用。

G suite document

查詢 G suite 所有的 ip address 的文件 https://support.google.com/a/answer/60764?hl=zh-Hant

Launch lisp from shell command

/usr/bin/sbcl --noinform --load gmail-suite.lisp --quit

Output

ip route add 64.233.160.0/19 via 192.168.1.1 dev enp2s0
ip route add 66.102.0.0/20 via 192.168.1.1 dev enp2s0
.. skip ..

Load script from lisp repl

(load "~/.org/gmail-suite.lisp")

Main program - lisp script

(ql:quickload :inferior-shell :silent t)
(ql:quickload :cl-ppcre :silent t)

(defpackage "GMAIL-SUITE"
(:use "COMMON-LISP" "INFERIOR-SHELL" "CL-PPCRE"))
(in-package "GMAIL-SUITE")

(let ((rev nil) (gw "192.168.1.1"))
(labels ((grep (match-str lst &key (start 0))
     (if (> start 0)
         (mapcar #'(lambda (x) (subseq x start))
                 (remove-if-not #'(lambda (x) (search match-str x)) lst))
         (remove-if-not #'(lambda (x) (search match-str x)) lst)))

       (spf-nslookup-raw-data-grep-spf1 (domain)
     (split " "
            (first
             (grep "spf1"
                   (run/lines (format nil "nslookup -q=txt ~A 8.8.8.8" domain)))))))

    (setq rev
      (mapcar #'(lambda (domain)
              (grep "ip4:" (spf-nslookup-raw-data-grep-spf1 domain) :start (length "ip4:")))
          (grep "include:" (spf-nslookup-raw-data-grep-spf1 "_spf.google.com") :start (length "include:"))))

    (map nil
     #'(lambda (x)
     (format t "ip route add ~A via ~A dev enp2s0~%" x gw))
     (reduce #'append rev))))

Other

Rewirte grep function with defmacro

grep 有段 code 是重複的,試著用 macro 寫寫看。心得是 macro 不好閱讀是真的,但沒有想像中的難上手,不過 macro 的特性讓人印象深刻,很特別可以用 code 生成 code。

(defmacro grep (match-str lst &key (start 0))
  (let (( grep-filter `(remove-if-not #'(lambda (x) (search ,match-str x)) ,lst )))
  (if (> start 0)
    `(mapcar #'(lambda (x) (subseq x ,start)) ,grep-filter)
    `,grep-filter)))
GS> (macroexpand-1 '(grep  "5:" '("1:2" "2:2" "3:2" "4:4" "5:5")))
(REMOVE-IF-NOT #'(LAMBDA (X) (SEARCH "5:" X)) '("1:2" "2:2" "3:2" "4:4" "5:5"))

GS> (macroexpand-1 '(grep  "3:" '("1:2" "2:2" "3:2" "4:4" "5:5") :start 2))
(MAPCAR #'(LAMBDA (X) (SUBSEQ X 2))
        (REMOVE-IF-NOT #'(LAMBDA (X) (SEARCH "3:" X))
                 '("1:2" "2:2" "3:2" "4:4" "5:5")))