logo


Create a module for Gentoo Eselect

I do Love eselect!

gentoo eselect Create a module for Gentoo EselectFor those who don’t know eselect is a ‘modular administration and configuration framework’. In simpler words it is a management tool shipped with Gentoo, able to switch between packages versions and configurations files, working with symbolic links and environmental variables.

Just to better clarify eselect job, it is able to make you switch between Java VM versions, Python releases , Gcc compilers and it makes it possible to choose your favorite editor.

Eselect is a modular tool, meaning that you just need to create a simple .eselect file to make it run your own commands. What I’m going to explain below is how to create a simple module to manage a symbolic link.

Aim of the tutorial

What I want to achieve in this little tutorial is to create a simple switch to quickly change my /etc/resolv.conf file. This file tells to any network interface where to look for DNS resolving.

As during last days I had problems with DNS, I was forced to switch very often from my default domain resolver (this case an internal server) to an external one ( OpenDns ). Using eselect for this purpose really simplified my life!

Preparation : create the ‘alternatives’

As we want to switch between two different configurations we need to create those alternatives. Open a terminal, cd to /etc and create the files. I created one called resolv.orig and one called resolv.opends, to be used when local DNS resolver is down.

# Going to /etc directory
cd /etc
# Copying original resolv.conf
# to the first alternative
cp resolv.conf resolv.orig
# Creating new resolv.conf alternative
# using OpenDNS IPs
echo -e "nameserver 208.67.222.222\nnameserver 208.67.220.220" > resolv.prova

Now we have to delete the original file and replace it with a symlink, obviously to the .orig file

# Deleting physical file
rm resolv.conf
# Creating symlink
ln -s resolv.orig resolv.conf

We are done with pre-configuration, let’s proceed with eselect module creation

Create the module

For a complete developer guide to eselect module creation, please refer to Gentoo Wiki official guide . This is just a ‘for examples’ guide for a quick start.

First of all all eselect modules should be located in your /usr/share/eselect/modules directory, so go there and create a new .eselect file

# Going into eselect modules directory
cd /usr/share/eselect/modules
# Creating a new module file
touch resolv.eselect

Now use your favorite editor to edit it. In this example I’m using vim

# Opening file with vim
vim resolv.eselect

Head section


As always the head section of the file contains meta informations about the module and the author, will just quickly review it below

# -*-eselect-*-  vim: ft=eselect
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: $

# This will appear when listing the available modules
DESCRIPTION="Manage the /etc/resolv.conf symlink"
# Maintainer email
MAINTAINER="personal@andreaolivato.net"
# Date, used to create a version
SVN_DATE='$Date: 2009-10-23 12:00:07 +0200 (Fri, 23 Oct 2009) $'
# Creating version from date
VERSION=$(svn_date_to_version "${SVN_DATE}")

Find the alternatives


The first important function we need to create is the one taking care of listing all the possible alternatives that we have for our symlink. This means that you have to list all the files which can be linked to resolv.conf . In our case, there are only two : resolv.orig and resolv.opendns.

The easiest procedure would be to write those files directly, but as we want to learn how to deal with eselect properly let’s create a bash function to list those two file. This way if in the future we would like to create a new alternative, we don’t need to modify our code.

In the below function I just listed (using ls command) all the files starting with resolv. in the /etc folder and then excludes (using grep -v) the original file, which is resolv.conf. This way we can add more alternative by creating resolv.xxx files. Here’s the code

find_targets() {
    local p
    for p in $(ls /etc/resolv.* | grep -v conf )
    do
        echo $p
    done;
}

Create and remove the symlink


Proceeding with our code, we now need to be able to remove and create the symlink.

To remove it, we just need to use the rm command like this

remove_symlink() {
	rm "/etc/resolv.conf"
}

To create the symlink, we need to deal with the user choice. This choice is represented by a number, identifying the file to switch the link to. This means that we need to associate a parameter passed to the function with the position of the choice in our file list.

set_symlink() {
    # Get the parameter
    local target=${1}
    # Check it is a number
    if is_number "${target}" ; then
        # Get the list of the files via the previously created function
        local targets=( $(find_targets) )
        # Get the file associated with the parameter passed
        target=${targets[target - 1]}
    fi

    # If the result file does not exist
    if [[ -z "$target" ]] ; then
        # We output an error
        die -q "Target "${1}" doesn't appear to be valid!"
   # While if it exists
    else
        # We create the link
        ln -s "${target}" "/etc/resolv.conf"
    fi
}

Put the things together


Now we got a function to list, one to remove and one to insert. We need to put them together and switch between them depending on the user choices. The following function receives the parameter from the user, checks it, remove the current link if it exists and the call the create function forwarding the parameter.

do_set() {

    if [[ -z ${1} ]] ; then
        # If no parameter was passed
        die -q "You didn't tell me what to set the symlink to"
    elif [[ -L /etc/resolv.conf ]] ; then
        # If the links exists try to remove it
        if ! remove_symlink ; then
            # If can't remove it output error
            die -q "Couldn't remove existing symlink"
        # Try to create
        elif ! set_symlink "${1}" ; then
            # If can't create, output error
            die -q "Couldn't set a new symlink"
        fi
    # If the link exists but is not a link but a physical file
    elif [[ -e /etc/resolv.conf ]] ; then
        # We have something strange, output error
        die -q "/etc/resolv.conf exists but is not a symlink"
    else
        # Try to create
        set_symlink "${1}" || die -q "Couldn't set a new symlink"
    fi
}

The complete file


Remaining needed functions are mostly descriptive and I’m not going to review them in detail. Below is the complete code I used for the module.

# -*-eselect-*-  vim: ft=eselect
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: $

DESCRIPTION="Manage the /etc/resolv.conf symlink"
MAINTAINER="personal@andreaolivato.net"
SVN_DATE='$Date: 2009-09-20 22:26:07 +0200 (Sun, 20 Sep 2009) $'
VERSION=$(svn_date_to_version "${SVN_DATE}")

find_targets() {
	local p
	for p in $(ls /etc/resolv.* | grep -v conf )
	do
        echo $p
	done;

}

remove_symlink() {
	rm "/etc/resolv.conf"
}

set_symlink() {
	local target=${1}
	if is_number "${target}" ; then
		local targets=( $(find_targets) )
		target=${targets[target - 1]}
	fi

	if [[ -z "$target" ]] ; then
		die -q "Target \"${1}\" doesn't appear to be valid!"
	else
		ln -s "${target}" "/etc/resolv.conf"
	fi
}

describe_show() {
	echo "Show the current resolv.conf symlink"
}

do_show() {
	write_list_start "Current resolv.conf symlink:"
	if [[ -L /etc/resolv.conf ]] ; then
		local resolv=$(canonicalise "/etc/resolv.conf")
		write_kv_list_entry "${resolv%/}" ""
	else
		write_kv_list_entry "(unset)" ""
	fi
}

describe_list() {
	echo "List available resolv.conf symlink targets"
}

do_list() {
	local i targets=( $(find_targets) )
	write_list_start "Available resolv.conf symlink targets:"
	for (( i = 0; i < ${#targets[@]}; i++ )) ; do
		[[ ${targets[i]} = \
			$(basename "$(canonicalise "/etc/resolv.conf")") ]] \
			&& targets[i]=$(highlight_marker "${targets[i]}")
	done
	write_numbered_list -m "(none found)" "${targets[@]}"
}

describe_set() {
	echo "Set a new resolv.conf symlink target"
}

describe_set_parameters() {
	echo ""
}

describe_set_options() {
	echo "target : Target name or number (from 'list' action)"
}

do_set() {
	if [[ -z ${1} ]] ; then
		die -q "You didn't tell me what to set the symlink to"
	elif [[ -L /etc/resolv.conf ]] ; then

		if ! remove_symlink ; then
			die -q "Couldn't remove existing symlink"
		elif ! set_symlink "${1}" ; then
			die -q "Couldn't set a new symlink"
		fi
	elif [[ -e /etc/resolv.conf ]] ; then
		die -q "/etc/resolv.conf exists but is not a symlink"
	else
		set_symlink "${1}" || die -q "Couldn't set a new symlink"
	fi
}

Usage

After you saved the file, you can start using the new module.

To list available files do

eselect resolv list

To set the original one

eselect resolv set 1

To set the OpenDNS one

eselect resolv set 2

To show the current choice

eselect resolv show
  • Pingback: Andrea Olivato (andreaolivato) 's status on Friday, 23-Oct-09 12:46:16 UTC - Identi.ca

  • linxiao

    Ugg Australia has recruited designers like Manolo Blahnik, Carlos Falchi, Rebecca Minkoff, Rafe pictured,and more to design high-end versions of the brand's trademark boots for its seventh annual Art & Sole auction.

    I have to assume these will be filed under unaffordable (which is good – more money for St. Jude!), but I'll still be going to the pickyouruggs.com Web site on December 1 to window shop and see what these designers have cooked up.

    I am trying to picture what I would do to make these high end… Real Italian leather? A pearl brooch? Other expensive ingredients and sparkles? Maybe the differences won't be that extreme, but I hope each designer puts his personal touch on the shoe. I'm certain at the very least you'll be able to pick out which Uggs came from Betsey Johnson (UGG Classic tall 5815 boots, please!).

    The event is likely to inspire as many interesting Ugg knockoffs as there are regular Ugg knockoffs, so it is possible we'll see something like this around town next year. It's not only a great event for charity but probably also a good move to keep Uggs alive and relevant… especially with the number of people who'd like to see them disappear for good!UGG boots on sale!

    I will of course keep wearing my Uggs because A) I have them and B) they are warm, but if your kid asks Santa for Where the Wild Things Are UGG boots… I feel for ya.