My content can

Hngnnngngng— plop

Invoking emacs daemon and client easily

Posted by Hugo Heden on March 21, 2009

#!/bin/bash

# http://hugoheden.wordpress.com/2009/03/21/invoking-emacs-daemon-and-client-easily/
# This script will invoke emacsclient. If there is no emacs daemon
# running, then the daemon is automatically started.

# If any of -nw, -t or -tty, or for that matter -c or --create-frame,
# is specified on the command line, then the script will just pass on
# all arguments to emacsclient.

# But if none of that is specified, this script will assume that this
# is interactive usage. If $DISPLAY is set, the script assumes that
# the user would prefer to invoke the emacsclient with the --no-wait
# flag, opening the specified file (if any) in an existing frame (in
# the current $DISPLAY).  If there no frame currently open (in the
# current $DISPLAY) the script will add --create-frame as well.

# Because of --no-wait, it is not a good idea to let the EDITOR
# variable point to this script without command line flags. Suggested
# values for EDITOR would be "<script> --create-frame " or "<script>
# -nw"

# Tested with emacs 23.0.9 packaged for Ubuntu 8.10:
# $ emacs-snapshot --version
# GNU Emacs 23.0.90.1
# $ emacsclient.emacs-snapshot -V
# emacsclient 23.0.90

##############

#set -x # Print lots of debugging info

this_script="$0" 
  # Useful for prefixing printouts, and for self-invoking this script

  # This script can invoke itself by giving the --alternate-editor
  # option to emacsclient. The MUST_START_EMACS_DAEMON environment
  # variable is used to keep track on that:
if [ "x$MUST_START_EMACS_DAEMON" != "x" ] ; then
    echo "$this_script: Starting emacs --daemon. Ignoring all arguments: $@" >&2
    emacs-snapshot --daemon
      # No need to sleep or anything because the daemon will not fork
      # (return) until fully started.
    exit 1
      # We return an error code because starting the daemon implies a
      # previous failure to invoke the client. See usage below.
fi

  # Internal helper function that invokes the client, but if that
  # fails at least daemon is started before an error code is returned.
function _invoke_client_orelse_start_daemon() {
      # Note that stuff printed to stdout may/will be interpreted by
      # caller... So be careful with printouts -- use stderr:>&2
    local MUST_START_EMACS_DAEMON=1
    export MUST_START_EMACS_DAEMON
      # This script itself is specified as --alternate-editor, and it
      # will make sure to (try to) start the daemon at least. See
      # above.
    emacsclient.emacs-snapshot "$@" --alternate-editor $this_script
    retval=$?
    unset MUST_START_EMACS_DAEMON
    return $retval
}

  # Invokes the client. Also starts the daemon if necessary.
function _invoke_client(){
  _invoke_client_orelse_start_daemon "$@" ||
  emacsclient.emacs-snapshot "$@"
}

args=( "$@" )
  # Need to be careful to treat args as an *array*, so that command
  # line arguments are preserved until we pass them on -- even though
  # they may be containing spaces.. See `man bash` for more about
  # using parantheses for arrays, and about stuff like "$@" and
  # "${args[@]}"

if [ "x$DISPLAY" != "x" ] ; then
    user_has_specified_frame=false;
    for opt in "$@" ; do
	case $opt in 
	    -t)   user_has_specified_frame=true; break ;; # breaks out of the loop
	    -tty) user_has_specified_frame=true; break ;;
	    -nw)  user_has_specified_frame=true; break ;;
	    -c)   user_has_specified_frame=true; break ;;
	    --create-frame) user_has_specified_frame=true; break ;;
	esac
    done

    if [ $user_has_specified_frame == false ] ; then
          # Hmm, is this the only situation where we want to add
          # --no-wait?
        args=( "--no-wait" "${args[@]}" )

	display="\"$DISPLAY\"" 
          # display will contain something like "", ":0.0" or
          # "localhost:10.0" (including the quotes)
	current_emacs_displays=`_invoke_client_orelse_start_daemon --eval "(x-display-list)"` 
          # current_emacs_displays will contain something like (":0.0"
          # "localhost:10.0") current_emacs_displays may also be empty
          # if there was no daemon running, of if there is no frame
          # open.
	if [[ ! "$current_emacs_displays" =~ "$display" ]] ; then
              # If there is a match (display is included in
              # current_emacs_displays), then there is already a frame
              # open in this $DISPLAY. *Otherwise* we'll add the
              # --create-frame option to the array:
            args=( "--create-frame" "${args[@]}" )
	fi
    fi

fi # if DISPLAY

_invoke_client "${args[@]}"

# TODO: the "emacsclient || (emacsdaemon && emacsclient)" construct is
# ugly when the emacsclient call fails due to error in arguments --
# the daemon is invoked, but since it is already started a big error
# message is emitted -- FIXED -- now using the --alternate-editor
# mechanism, which works more gracefully.

# TODO: Check all if-statemenst for potentially empty values, for
# example "$current_emacs_displays" ..?

Posted in Uncategorized | Leave a Comment »

dnsmasq

Posted by Hugo Heden on March 8, 2009

Abstract

The host running dnsmasq:

1) Wherever  Static IP is configured the first “DNS Servers” entry  should specify 127.0.0.1 and the second should specify 192.168.0.254 (or whatever IP the nearest upstream DNS server has).

2) /etc/hosts.dnsmasq:

foohost 192.168.1.100

3)  /etc/dnsmasq.conf

domain-needed
bogus-priv
no-hosts
addn-hosts=/etc/hosts.dnsmasq
expand-hosts
domain=foolan
dhcp-range=192.168.1.50,192.168.1.100,12h
dhcp-host=ahost,192.168.1.70,30m
#dhcp-host=otherhost,192.168.1.71,12h
#dhcp-host=yetanotherhost,192.168.1.72,30m
dhcp-option=option:router,192.168.1.1

Intro

I have a few computers at home (all running Ubuntu Linux 8.10, Intrepid Ibex) forming a small home network. I use dnsmasq to achieve the following:

  • Any host can be plugged in “without configuration”, i.e the dhcp-server functionality within dnsmasq is used.
  • After having been plugged in, hosts are able to ping or connect to each other by host name (thus not only by ip numbers), still without configuration, i.e that dhcp-server will be used together with the DNS functionality that dnsmasq provides.
  • Some of the hosts need a “constant” IP within the LAN (or “static” if you will, though using dhcp). This is needed for port forwarding to these hosts (so that they can be used for bittorrent and as various types of servers). We achieve this by letting dnsmasq manage a list of hostnames and their respective “constant” IP addresses within the LAN. So there is only one place within the whole LAN where that information is maintained, see below. The hosts themselves are still using zero configuration dhcp.
  • dnsmasq also works as a local dns cache for the LAN, which speeds up web browsing.
  • All this is very easy to set up

I tried for a while to set up a WINS server (using samba), but I could never really make that working..

A limitation is that the host running dnsmasq needs to be up pretty all the time (or at least whenever a host on the network needs web access). I have a desktop computer constantly turned on anyway (hosting a few server processes) that dnsmasq can run on.

Another option would be to install it dnsmasq on a router. This would be your only option if there is only Windows computers on your network, because dnsmasq does not run on Windows. I have no experience with this, but see for example Tomato Firmware.

So, how do we set up all this?

The host running dnsmasq has a static ip within the LAN. We want other applications on that same host to use dnsmasq for DNS services, and not some other DNS server on some other host. So, within Network Manager (or wherever that Static IP was configured) the first “DNS Servers” entry  should specify 127.0.0.1. When the connection is enabled, NetworkManager will generate a /etc/resolv.conf containing something like the following:

# Generated by NetworkManager
nameserver 127.0.0.1

By default, dnsmasq will read /etc/resolv.conf and use the hosts specified there (the lines starting with “nameserver”) as “upstream nameservers” to forward non-local DNS-requests to. In this case that file will point back to localhost (127.0.0.1), see above. But that’s ok, dnsmasq will understand to ignore 127.0.0.1 and look at the other lines in /etc/resolv.conf. In my case I will need to add the ip address that my adsl-modem has on the LAN, because the modem in turn is auto-configured by the ISP (dhcp) to know what dns servers to contact further upstream. So, within Network Manager (or wherever that Static IP was configured) the second “DNS Servers” entry  should specify 192.168.0.254. When the connection is enabled, NetworkManager will then generate a /etc/resolv.conf containing something like the following:

# Generated by NetworkManager
nameserver 127.0.0.1
nameserver 192.168.0.254

Further, dnsmasq is configured to ignore the usual /etc/hosts and use a custom hosts-file instead, /etc/hosts.dnsmasq,  containing something like the following (“foohost” is the name of the host running dnsmasq)

foohost 192.168.1.100

/etc/dnsmasq.conf would then need the entry no-hosts to tell dnsmasq to ignore the usual hosts-file, and the entry addn-hosts=/etc/hosts.dnsmasq which specifies what file to use instead.

Wrap-up

A suitable /etc/dnsmasq.conf is shown above. (As always, do a backup of the original before experimenting.) Most of the options are well documented elsewhere (for example in the example configuration file and the man-page). Note the dhcp-option=option:router,192.168.1.1 line which tells dnsmasq to tell any dhcp-clients what the gateway of the network is. In my case I’ve specified the address to my router.

Posted in Uncategorized | Leave a Comment »

Copy/paste with emacs in terminal

Posted by Hugo Heden on March 8, 2009

I often run emacs in a terminal window. The following is a way to get copy-paste “working” to and from other applications. Note that it requires xsel, “a command-line program for getting and setting the contents of the X selection”. See also http://shreevatsa.wordpress.com/2006/10/22/emacs-copypaste-and-x/

;; http://hugoheden.wordpress.com/2009/03/08/copypaste-with-emacs-in-terminal/
;; I prefer using the "clipboard" selection (the one the
;; typically is used by c-c/c-v) before the primary selection
;; (that uses mouse-select/middle-button-click)
(setq x-select-enable-clipboard t)

;; If emacs is run in a terminal, the clipboard- functions have no
;; effect. Instead, we use of xsel, see
;; http://www.vergenet.net/~conrad/software/xsel/ -- "a command-line
;; program for getting and setting the contents of the X selection"
(unless window-system
  ;; Callback for when user cuts
  (defun xsel-cut-function (text &optional push)
    ;; Insert text to temp-buffer, and "send" content to xsel stdin
    (with-temp-buffer
      (insert text)
      ;; I prefer using the "clipboard" selection (the one the
      ;; typically is used by c-c/c-v) before the primary selection
      ;; (that uses mouse-select/middle-button-click)
      (call-process-region (point-min) (point-max) "xsel" nil 0 nil "--clipboard" "--input")))
  ;; Call back for when user pastes
  (defun xsel-paste-function()
    ;; Find out what is current selection by xsel. If it is different
    ;; from the top of the kill-ring (car kill-ring), then return
    ;; it. Else, nil is returned, so whatever is in the top of the
    ;; kill-ring will be used.
    (let ((xsel-output (shell-command-to-string "xsel --clipboard --output")))
      (unless (string= (car kill-ring) xsel-output)
	xsel-output )))
  ;; Attach callbacks to hooks
  (setq interprogram-cut-function 'xsel-cut-function)
  (setq interprogram-paste-function 'xsel-paste-function)
  ;; Idea from
  ;; http://shreevatsa.wordpress.com/2006/10/22/emacs-copypaste-and-x/
  ;; http://www.mail-archive.com/help-gnu-emacs@gnu.org/msg03577.html
  )

Thanks to Nikolaj Schumacher and Miles Bader on the help-gnu-emacs mailing list for helping out.

Posted in Uncategorized | 4 Comments »

dnsmasq and /etc/hosts

Posted by Hugo Heden on February 24, 2009

Abstract

/etc/hosts.dnsmasq:
192.168.1.100 foohost
(/etc/hosts is left alone)
/etc/dnsmasq.conf:

no-hosts
addn-hosts=/etc/hosts.dnsmasq

Intro

dnsmasq will, by default, read the contents of /etc/hosts and use the information there for looking up those hosts that are configured to have a static IP on the LAN. (Hosts using dnsmasq as a dhcp-server are not specified there).

Problem

However, in Debian, Ubuntu  and others, /etc/hosts seems to contain lines that break this — something like the following (the host name is foohost in this example):

127.0.0.1 foohost localhost.localdomain localhost
127.0.1.1 foohost

A consequence is that if another host on the network for example tries to ping foohost, the DNS lookup performed by dnsmasq on foohost will return 127.0.0.1 or 127.0.1.1, which will not be the address that was intended—the other host will end up pinging itself.

Solution

Now, apparently the above /etc/hosts is broken — for Debian and derivatives it should be rewritten as

127.0.0.1  localhost
127.0.1.1 foohost

– see  [1], [2] and Google.

Further,  if the host has a permanent IP then that IP should be specified instead of 127.0.1.1. And the host running dnsmasq will need to have a static IP, so problem solved:

# Fixed /etc/hosts:
127.0.0.1  localhost
192.168.1.100 foohost

Other solution

I think I prefer to leave /etc/hosts alone though. I suspect various network configuration tools  will edit that file, and may unfix it.  dnsmasq can instead be configured to use another host-file (as suggested by Nils Kassube on ubuntu-users). So, I have added a file /etc/hosts.dnsmasq, specifying the static ip of the host running dnsmasq:

192.168.1.100 foohost

/etc/dnsmasq.conf would then need the entry no-hosts to tell dnsmasq to ignore the usual hosts-file, and the entry addn-hosts=/etc/hosts.dnsmasq which specifies what file to use instead.

(The above mentioned file, /etc/hosts.dnsmasq, could also contain other typical /etc/hosts entries for other hosts on the LAN using static ip, as described in the very nice article on enterprisenetworkingplanet … but why would we do that when all hosts can use configuration-less dhcp instead?)

[1] http://www.debian.org/doc/manuals/reference/ch-gateway.en.html#s-net-dns

[2] https://bugs.launchpad.net/ubuntu/+source/netcfg/+bug/19775/comments/23

Posted in Uncategorized | 1 Comment »

Port forwarding through modem and router

Posted by Hugo Heden on February 10, 2009

I have a SpeedTouch 510 ADSL modem at home (firmware 4.2.7.16.0), and behind that there is a Linksys WRT54G wireless router. Being a total rookie I had big trouble setting up port forwarding for this system, so I decided to document this.

There are probably a zillion different ways to do this, and I tried many combinations of settings. The following was the only variant I managed to get working:

-A-

The modem will be configured to be completely “open” i.e forward all incoming connections to the router, by specifying the router IP address as the “NAPT – Default Server” within the modem web-UI. (NAPT stands for Network Address and Port Translation.)

-B-

The router will act as a firewall (except for the port forwarding that will be configured below). The router IP address will need to be static. Had it had a dynamic IP (using for example the modems built-in dhcp-server), that “NAPT – Default Server” setting within the modem web-UI would have needed to be manually updated whenever the router IP changed. Obviously very inconvenient.

Pitfall: I wanted to just quickly test port forwarding without fiddling with setting the router IP address to static. But no, that just did not seem to work. The modem seemed to refuse to forward any connections if “NAPT – Default Server” was set to … to a dynamic IP address handed out by the modem..? Or something. So, my tip would be to start with setting the router to have a static IP. That worked a lot better.

So, start with setting the router to have a static IP, say 192.168.0.1, instead of a dynamic one. On the Linksys this is done in the web-UI under “Setup => Basic Setup”. When choosing Static IP in the drop-down, the UI seemed to intelligently fill in some of the needed values.

  • Internet IP Address: 192.168.0.1 <is typical>
  • Subnet Mask: 255.255.255.0 <is typical>
  • Gateway: <The LAN IP address that the modem has, 192.168.0.254 maybe>
  • Static DNS 1: <The LAN IP address that the modem has, same as Gateway>

Fiddle with this until there is a reliable internet connection again.. Use Google.. Perhaps the modem and/or the router need to be restarted?

-C-

The router in turn will act as a firewall, but some incoming connections (coming from the Internet via the modem) will be forwarded — as specified in the router web-UI under “Application & Gaming” => “Port Range Forward”. Here we specify port(range)s that we want forwarded, and to what IP address within the LAN each port(range) will be forwarded:

  • Application (not sure what this is for)
  • Start (of port range)
  • End (of port range)
  • Protocol (tcp, udp or both)
  • IP-Address (LAN address to forward to, for example 192.168.1.100)

Step by step

After having configured the router to have a static IP (see -B- above), the following steps outline what needs to be performed.

-1-

We need a working Internet connection so that we can test that we don’t break stuff. Visit a site that will assist in testing our port-forwarding. A good candidate seems to be:

http://www.yougetsignal.com/tools/open-ports/

-2-

For testing purposes, temporarily open some port on the local desktop, say port 55555, by opening a program that listens for incoming connections, for example sshd:

$ sudo /usr/sbin/sshd -D -p 55555

Verify on yougetsignal.com that the port is not (yet) open on the modem when connected to from the Internet.

-3-

In the modem web-UI, under “Advanced => NAPT => Default Server”, enter the static IP that the router now has (see -B- above, 192.168.0.1 in that example).

-4-

As described in -C- above, configure the router to forward ports… Verify on yougetsignal.com that the port is now open on the modem when connected to from the Internet.

-5-

Shut down whatever program was opened in step -2- above.

-DONE-

QUESTION: Should the modem firewall be turned off now that we forward everything to the router anyway? I guess so.

PS: See also these sites that does things in a way I could not really understand or get to work:
http://portforward.com/
http://www.xs4all.nl/~eeuwen/speedtouch_510.htm

PS: I am not able go get UPnP (Universal Plug and Play) in the linksys router working (using the Administration=>Management=>UPnP area in the web-UI) even if I disable the firewall within the modem and enable UPnP within the modem. Perhaps UPnP does not work in “two layers” (router *and* modem).. or what is the problem? I am using the Transmission Bittorrent client which supports UPnP. Might as well turn off UPnP then, both in the router and in the modem (Advanced=>NAPT=>UPnP), as it may pose a security risk..?

Posted in Uncategorized | Leave a Comment »