A friend asked me how to retrieve your IP-number in emacs; he needs it to
figure out in which of various networks he lives, to update proxy settings and the like. He
had found a decade-old function get-ip-address
on the internet, and
thought (correctly!) that it can't be that hard.
So, fortunately, it wasn't too hard to do it a bit better, esp. with all the
improvements in emacs in the last ten years.
The somewhat-ugly-but-it-works solution is to use the output of the ifconfig
tool:
(defun get-ip-address (&optional dev)
"get the IP-address for device DEV (default: eth0)"
(let ((dev (if dev dev "eth0")))
(substring ;; chop the final "\n"
(shell-command-to-string
(concat
"ifconfig " dev
"|grep 'inet addr'|sed 's/.*inet addr:\\(\\([0-9\.]\\)*\\).*/\\1/'"))
0 -1)))
Now, calling
(get-ip-address "eth0")
or (get-ip-address "lo")
in your scriptswill get you the IP-number. Obviously, this only works on systems that have
this
ifconfig
, and is also vulnerable to small changes in the output. Don't even ask about IPv6.
The solution does give us a nice example of using shell-command-to-string
,
which is really useful function to integrate with all kinds of external tools;
the difference with decade-old get=ip-address
is striking.
However, we can do even better in these modern times. More recent versions of
emacs provide nice networking functionality:
(defun get-ip-address (&optional dev)
"get the IP-address for device DEV (default: eth0)"
(let ((dev (if dev dev "eth0")))
(format-network-address (car (network-interface-info dev)) t)))
All fine - but unfortunately, this does not work on Windows; there is no such
thing as
network-interface-info
there, not even in the latest Emacsincarnations. Is there nothing else we can do on Windows? Well… we can go
back to the first solution (using
shell-command-to-string
, and see if we canuse it with Windows'
ipconfig
tool. Something like:(defun get-ip-address ()
"Win32: get the IP-address of the first network interface"
(let ((ipconfig (shell-command-to-string "ipconfig | findstr Address")))
(string-match "\\(\\([0-9]+.\\)+[0-9]+\\)" ipconfig)
(match-string 0 ipconfig)))
The Windows version does not support choosing the interface; I'll leave that
as an excercise to a reader with some more Win-fu; that same reader might also
have a solution that does not involve
ipconfig
, but uses some Win32-API. Andof course, that user is invited to help the emacs development team to add a
Win32 version of
network-interface-info
.
No comments:
Post a Comment