Search Results: "frob"

9 February 2023

Jonathan McDowell: Building a read-only Debian root setup: Part 2

This is the second part of how I build a read-only root setup for my router. You might want to read part 1 first, which covers the initial boot and general overview of how I tie the pieces together. This post will describe how I build the squashfs image that forms the main filesystem. Most of the build is driven from a script, make-router, which I ll dissect below. It s highly tailored to my needs, and this is a fairly lengthy post, but hopefully the steps I describe prove useful to anyone trying to do something similar.
Breakdown of make-router
#!/bin/bash
# Either rb3011 (arm) or rb5009 (arm64)
#HOSTNAME="rb3011"
HOSTNAME="rb5009"
if [ "x$ HOSTNAME " == "xrb3011" ]; then
	ARCH=armhf
elif [ "x$ HOSTNAME " == "xrb5009" ]; then
	ARCH=arm64
else
	echo "Unknown host: $ HOSTNAME "
	exit 1
fi

It s a bash script, and I allow building for either my RB3011 or RB5009, which means a different architecture (32 vs 64 bit). I run this script on my Pi 4 which means I don t have to mess about with QemuUserEmulation.
BASE_DIR=$(dirname $0)
IMAGE_FILE=$(mktemp --tmpdir router.$ ARCH .XXXXXXXXXX.img)
MOUNT_POINT=$(mktemp -p /mnt -d router.$ ARCH .XXXXXXXXXX)
# Build and mount an ext4 image file to put the root file system in
dd if=/dev/zero bs=1 count=0 seek=1G of=$ IMAGE_FILE 
mkfs -t ext4 $ IMAGE_FILE 
mount -o loop $ IMAGE_FILE  $ MOUNT_POINT 

I build the image in a loopback ext4 file on tmpfs (my Pi4 is the 8G model), which makes things a bit faster.
# Add dpkg excludes
mkdir -p $ MOUNT_POINT /etc/dpkg/dpkg.cfg.d/
cat <<EOF > $ MOUNT_POINT /etc/dpkg/dpkg.cfg.d/path-excludes
# Exclude docs
path-exclude=/usr/share/doc/*
# Only locale we want is English
path-exclude=/usr/share/locale/*
path-include=/usr/share/locale/en*/*
path-include=/usr/share/locale/locale.alias
# No man pages
path-exclude=/usr/share/man/*
EOF

Create a dpkg excludes config to drop docs, man pages and most locales before we even start the bootstrap.
# Setup fstab + mtab
echo "# Empty fstab as root is pre-mounted" > $ MOUNT_POINT /etc/fstab
ln -s ../proc/self/mounts $ MOUNT_POINT /etc/mtab
# Setup hostname
echo $ HOSTNAME  > $ MOUNT_POINT /etc/hostname
# Add the root SSH keys
mkdir -p $ MOUNT_POINT /root/.ssh/
cat <<EOF > $ MOUNT_POINT /root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAv8NkUeVdsVdegS+JT9qwFwiHEgcC9sBwnv6RjpH6I4d3im4LOaPOatzneMTZlH8Gird+H4nzluciBr63hxmcFjZVW7dl6mxlNX2t/wKvV0loxtEmHMoI7VMCnrWD0PyvwJ8qqNu9cANoYriZRhRCsBi27qPNvI741zEpXN8QQs7D3sfe4GSft9yQplfJkSldN+2qJHvd0AHKxRdD+XTxv1Ot26+ZoF3MJ9MqtK+FS+fD9/ESLxMlOpHD7ltvCRol3u7YoaUo2HJ+u31l0uwPZTqkPNS9fkmeCYEE0oXlwvUTLIbMnLbc7NKiLgniG8XaT0RYHtOnoc2l2UnTvH5qsQ== noodles@earth.li
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDQb9+qFemcwKhey3+eTh5lxp+3sgZXW2HQQEZMt9hPvVXk+MiiNMx9WUzxPJnwXqlmmVdKsq+AvjA0i505Pp8fIj5DdUBpSqpLghmzpnGuob7SSwXYj+352hjD52UC4S0KMKbIaUpklADgsCbtzhYYc4WoO8F7kK63tS5qa1XSZwwRwPbYOWBcNocfr9oXCVWD9ismO8Y0l75G6EyW8UmwYAohDaV83pvJxQerYyYXBGZGY8FNjqVoOGMRBTUcLj/QTo0CDQvMtsEoWeCd0xKLZ3gjiH3UrknkaPra557/TWymQ8Oh15aPFTr5FvKgAlmZaaM0tP71SOGmx7GpCsP4jZD1Xj/7QMTAkLXb+Ou6yUOVM9J4qebdnmF2RGbf1bwo7xSIX6gAYaYgdnppuxqZX1wyAy+A2Hie4tUjMHKJ6OoFwBsV1sl+3FobrPn6IuulRCzsq2aLqLey+PHxuNAYdSKo7nIDB3qCCPwHlDK52WooSuuMidX4ujTUw7LDTia9FxAawudblxbrvfTbg3DsiDBAOAIdBV37HOAKu3VmvYSPyqT80DEy8KFmUpCEau59DID9VERkG6PWPVMiQnqgW2Agn1miOBZeIQV8PFjenAySxjzrNfb4VY/i/kK9nIhXn92CAu4nl6D+VUlw+IpQ8PZlWlvVxAtLonpjxr9OTw== noodles@yubikey
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0I8UHj4IpfqUcGE4cTvLB0d2xmATSUzqtxW6ZhGbZxvQDKJesVW6HunrJ4NFTQuQJYgOXY/o82qBpkEKqaJMEFHTCjcaj3M6DIaxpiRfQfs0nhtzDB6zPiZn9Suxb0s5Qr4sTWd6iI9da72z3hp9QHNAu4vpa4MSNE+al3UfUisUf4l8TaBYKwQcduCE0z2n2FTi3QzmlkOgH4MgyqBBEaqx1tq7Zcln0P0TYZXFtrxVyoqBBIoIEqYxmFIQP887W50wQka95dBGqjtV+d8IbrQ4pB55qTxMd91L+F8n8A6nhQe7DckjS0Xdla52b9RXNXoobhtvx9K2prisagsHT noodles@cup
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK6iGog3WbNhrmrkglNjVO8/B6m7mN6q1tMm1sXjLxQa+F86ETTLiXNeFQVKCHYrk8f7hK0d2uxwgj6Ixy9k0Cw= noodles@sevai
EOF

Setup fstab, the hostname and SSH keys for root.
# Bootstrap our install
debootstrap \
	--arch=$ ARCH  \
	--include=collectd-core,conntrack,dnsmasq,ethtool,iperf3,kexec-tools,mosquitto,mtd-utils,mtr-tiny,ppp,tcpdump,rng-tools5,ssh,watchdog,wget \
	--exclude=dmidecode,isc-dhcp-client,isc-dhcp-common,makedev,nano \
	bullseye $ MOUNT_POINT  https://deb.debian.org/debian/

Actually do the debootstrap step, including a bunch of extra packages that we want.
# Install mqtt-arp
cp $ BASE_DIR /debs/mqtt-arp_1_$ ARCH .deb $ MOUNT_POINT /tmp
chroot $ MOUNT_POINT  dpkg -i /tmp/mqtt-arp_1_$ ARCH .deb
rm $ MOUNT_POINT /tmp/mqtt-arp_1_$ ARCH .deb
# Frob the mqtt-arp config so it starts after mosquitto
sed -i -e 's/After=.*/After=mosquitto.service/' $ MOUNT_POINT /lib/systemd/system/mqtt-arp.service

I haven t uploaded mqtt-arp to Debian, so I install a locally built package, and ensure it starts after mosquitto (the MQTT broker), given they re running on the same host.
# Frob watchdog so it starts earlier than multi-user
sed -i -e 's/After=.*/After=basic.target/' $ MOUNT_POINT /lib/systemd/system/watchdog.service
# Make sure the watchdog is poking the device file
sed -i -e 's/^#watchdog-device/watchdog-device/' $ MOUNT_POINT /etc/watchdog.conf

watchdog timeouts were particularly an issue on the RB3011, where the default timeout didn t give enough time to reach multiuser mode before it would reset the router. Not helpful, so alter the config to start it earlier (and make sure it s configured to actually kick the device file).
# Clean up docs + locales
rm -r $ MOUNT_POINT /usr/share/doc/*
rm -r $ MOUNT_POINT /usr/share/man/*
for dir in $ MOUNT_POINT /usr/share/locale/*/; do
	if [ "$ dir " != "$ MOUNT_POINT /usr/share/locale/en/" ]; then
		rm -r $ dir 
	fi
done

Clean up any docs etc that ended up installed.
# Set root password to root
echo "root:root"   chroot $ MOUNT_POINT  chpasswd

The only login method is ssh key to the root account though I suppose this allows for someone to execute a privilege escalation from a daemon user so I should probably randomise this. Does need to be known though so it s possible to login via the serial console for debugging.
# Add security to sources.list + update
echo "deb https://security.debian.org/debian-security bullseye-security main" >> $ MOUNT_POINT /etc/apt/sources.list
chroot $ MOUNT_POINT  apt update
chroot $ MOUNT_POINT  apt -y full-upgrade
chroot $ MOUNT_POINT  apt clean
# Cleanup the APT lists
rm $ MOUNT_POINT /var/lib/apt/lists/www.*
rm $ MOUNT_POINT /var/lib/apt/lists/security.*

Pull in any security updates, then clean out the APT lists rather than polluting the image with them.
# Disable the daily APT timer
rm $ MOUNT_POINT /etc/systemd/system/timers.target.wants/apt-daily.timer
# Disable daily dpkg backup
cat <<EOF > $ MOUNT_POINT /etc/cron.daily/dpkg
#!/bin/sh
# Don't do the daily dpkg backup
exit 0
EOF
# We don't want a persistent systemd journal
rmdir $ MOUNT_POINT /var/log/journal

None of these make sense on a router.
# Enable nftables
ln -s /lib/systemd/system/nftables.service \
	$ MOUNT_POINT /etc/systemd/system/sysinit.target.wants/nftables.service

Ensure we have firewalling enabled automatically.
# Add systemd-coredump + systemd-timesync user / group
echo "systemd-timesync:x:998:" >> $ MOUNT_POINT /etc/group
echo "systemd-coredump:x:999:" >> $ MOUNT_POINT /etc/group
echo "systemd-timesync:!*::" >> $ MOUNT_POINT /etc/gshadow
echo "systemd-coredump:!*::" >> $ MOUNT_POINT /etc/gshadow
echo "systemd-timesync:x:998:998:systemd Time Synchronization:/:/usr/sbin/nologin" >> $ MOUNT_POINT /etc/passwd
echo "systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin" >> $ MOUNT_POINT /etc/passwd
echo "systemd-timesync:!*:47358::::::" >> $ MOUNT_POINT /etc/shadow
echo "systemd-coredump:!*:47358::::::" >> $ MOUNT_POINT /etc/shadow
# Create /etc/.pwd.lock, otherwise it'll end up in the overlay
touch $ MOUNT_POINT /etc/.pwd.lock
chmod 600 $ MOUNT_POINT /etc/.pwd.lock

Create a number of users that will otherwise get created at boot, and a lock file that will otherwise get created anyway.
# Copy config files
cp --recursive --preserve=mode,timestamps $ BASE_DIR /etc/* $ MOUNT_POINT /etc/
cp --recursive --preserve=mode,timestamps $ BASE_DIR /etc-$ ARCH /* $ MOUNT_POINT /etc/
chroot $ MOUNT_POINT  chown mosquitto /etc/mosquitto/mosquitto.users
chroot $ MOUNT_POINT  chown mosquitto /etc/ssl/mqtt.home.key

There are config files that are easier to replace wholesale, some of which are specific to the hardware (e.g. related to network interfaces). See below for some more details.
# Build symlinks into flash for boot / modules
ln -s /mnt/flash/lib/modules $ MOUNT_POINT /lib/modules
rmdir $ MOUNT_POINT /boot
ln -s /mnt/flash/boot $ MOUNT_POINT /boot

The kernel + its modules live outside the squashfs image, on the USB flash drive that the image lives on. That makes for easier kernel upgrades.
# Put our git revision into os-release
echo -n "GIT_VERSION=" >> $ MOUNT_POINT /etc/os-release
(cd $ BASE_DIR  ; git describe --tags) >> $ MOUNT_POINT /etc/os-release

Always helpful to be able to check the image itself for what it was built from.
# Add some stuff to root's .bashrc
cat << EOF >> $ MOUNT_POINT /root/.bashrc
alias ls='ls -F --color=auto'
eval "\$(dircolors)"
case "\$TERM" in
xterm* rxvt*)
	PS1="\\[\\e]0;\\u@\\h: \\w\a\\]\$PS1"
	;;
*)
	;;
esac
EOF

Just some niceties for when I do end up logging in.
# Build the squashfs
mksquashfs $ MOUNT_POINT  /tmp/router.$ ARCH .squashfs \
	-comp xz

Actually build the squashfs image.
# Save the installed package list off
chroot $ MOUNT_POINT  dpkg --get-selections > /tmp/wip-installed-packages

Save off the installed package list. This was particularly useful when trying to replicate the existing router setup and making sure I had all the important packages installed. It doesn t really serve a purpose now.
In terms of the config files I copy into /etc, shared across both routers are the following:
Breakdown of shared config
  • apt config (disable recommends, periodic updates):
    • apt/apt.conf.d/10periodic, apt/apt.conf.d/local-recommends
  • Adding a default, empty, locale:
    • default/locale
  • DNS/DHCP:
    • dnsmasq.conf, dnsmasq.d/dhcp-ranges, dnsmasq.d/static-ips
    • hosts, resolv.conf
  • Enabling IP forwarding:
    • sysctl.conf
  • Logs related:
    • logrotate.conf, rsyslog.conf
  • MQTT related:
    • mosquitto/mosquitto.users, mosquitto/conf.d/ssl.conf, mosquitto/conf.d/users.conf, mosquitto/mosquitto.acl, mosquitto/mosquitto.conf
    • mqtt-arp.conf
    • ssl/lets-encrypt-r3.crt, ssl/mqtt.home.key, ssl/mqtt.home.crt
  • PPP configuration:
    • ppp/ip-up.d/0000usepeerdns, ppp/ipv6-up.d/defaultroute, ppp/pap-secrets, ppp/chap-secrets
    • network/interfaces.d/pppoe-wan
The router specific config is mostly related to networking:
Breakdown of router specific config
  • Firewalling:
    • nftables.conf
  • Interfaces:
    • dnsmasq.d/interfaces
    • network/interfaces.d/eth0, network/interfaces.d/p1, network/interfaces.d/p2, network/interfaces.d/p7, network/interfaces.d/p8
  • PPP config (network interface piece):
    • ppp/peers/aquiss
  • SSH keys:
    • ssh/ssh_host_ecdsa_key, ssh/ssh_host_ed25519_key, ssh/ssh_host_rsa_key, ssh/ssh_host_ecdsa_key.pub, ssh/ssh_host_ed25519_key.pub, ssh/ssh_host_rsa_key.pub
  • Monitoring:
    • collectd/collectd.conf, collectd/collectd.conf.d/network.conf

15 June 2016

Reproducible builds folks: Reproducible builds: week 59 in Stretch cycle

What happened in the Reproducible Builds effort between June 5th and June 11th 2016: Media coverage Ed Maste gave a talk at BSDCan 2016 on reproducible builds (slides, video). GSoC and Outreachy updates Weekly reports by our participants: Documentation update - Ximin Luo proposed a modification to our SOURCE_DATE_EPOCH spec explaining FORCE_SOURCE_DATE. Some upstream build tools (e.g. TeX, see below) have expressed a desire to control which cases of embedded timestamps should obey SOURCE_DATE_EPOCH. They were not convinced by our arguments on why this is a bad idea, so we agreed on an environment variable FORCE_SOURCE_DATE for them to implement their desired behaviour - named generically, so that at least we can set it centrally. For more details, see the text just linked. However, we strongly urge most build tools not to use this, and instead obey SOURCE_DATE_EPOCH unconditionally in all cases. Toolchain fixes Packages fixed The following 16 packages have become reproducible due to changes in their build-dependencies: apertium-dan-nor apertium-swe-nor asterisk-prompt-fr-armelle blktrace canl-c code-saturne coinor-symphony dsc-statistics frobby libphp-jpgraph paje.app proxycheck pybit spip tircd xbs The following 5 packages are new in Debian and appear to be reproducible so far: golang-github-bowery-prompt golang-github-pkg-errors golang-gopkg-dancannon-gorethink.v2 libtask-kensho-perl sspace The following packages had older versions which were reproducible, and their latest versions are now reproducible again after being fixed: The following packages have become reproducible after being fixed: Some uploads have fixed some reproducibility issues, but not all of them: Patches submitted that have not made their way to the archive yet: Package reviews 68 reviews have been added, 19 have been updated and 28 have been removed in this week. New and updated issues: 26 FTBFS bugs have been reported by Chris Lamb, 1 by Santiago Vila and 1 by Sascha Steinbiss. diffoscope development strip-nondeterminism development disorderfs development tests.reproducible-builds.org Misc. Steven Chamberlain submitted a patch to FreeBSD's makefs to allow reproducible builds of the kfreebsd installer. Ed Maste committed a patch to FreeBSD's binutils to enable determinstic archives by default in GNU ar. Helmut Grohne experimented with cross+native reproductions of dash with some success, using rebootstrap. This week's edition was written by Ximin Luo, Chris Lamb, Holger Levsen, Mattia Rizzolo and reviewed by a bunch of Reproducible builds folks on IRC.

30 May 2016

Reproducible builds folks: Reproducible builds: week 57 in Stretch cycle

What happened in the Reproducible Builds effort between May 22nd and May 28th 2016: Media coverage Documentation update Toolchain fixes Packages fixed The following 18 packages have become reproducible due to changes in their build dependencies: canl-c configshell dbus-java dune-common frobby frown installation-guide jexcelapi libjsyntaxpane-java malaga octave-ocs paje.app pd-boids pfstools r-cran-rniftilib scscp-imcce snort vim-addon-manager The following packages have become reproducible after being fixed: Some uploads have fixed some reproducibility issues, but not all of them: Patches submitted that have not made their way to the archive yet: Package reviews 123 reviews have been added, 57 have been updated and 135 have been removed in this week. 21 FTBFS bugs have been reported by Chris Lamb and Santiago Vila. strip-nondeterminism development tests.reproducible-builds.org Misc. This week's edition was written by Reiner Herrmann and Holger Levsen and reviewed by a bunch of Reproducible builds folks on IRC.

30 November 2014

Enrico Zini: cxx11-talk-notes

C++11 talk notes On 2014-11-27 I gave a talk about C++ and new features introduced with C++11: these are the talk notes. See cxx11-talk-examples for the examples. (note: I had to add U+2063 INVISIBLE SEPARATOR to prevent noreturn statements to be misinterpreted by the blog formatter. If you copypaste the code and encounter issues, you may want to delete the noreturn statements and retype them) Overview of programming languages
It has to be as fast as possible, so interpreted languages are out. You don't want to micro manage memory, so C is out. You don't want to require programmers to have a degree, so C++ is out. You want fast startup and not depend on a big runtime, so Java is out. [...] (Bram Moolenaar)
C++ secret cultist protip
Do not call up what you cannot put down.
C++ is a compiled language It is now possible to use the keyword constexpr to mark functions and objects that can be used at compile time:
/*
 * constexpr tells the compiler that a variable or function can be evaluated at
 * compile time.
 *
 * constexpr functions can also be run at run time, if they are called with
 * values not known at compile time.
 *
 * See http://en.cppreference.com/w/cpp/language/constexpr for more nice examples
 *
 * It can be used to avoid using constants in code, and using instead functions
 * for computing hardware bitfields or physical values, without losing in
 * efficiency.
 */
#include <iostream>
using namespace std;
constexpr int factorial(int n)
 
    return n <= 1 ? 1 : (n * factorial(n-1));
 
int main()
 
    cout << "Compile time factorial of 6: " << factorial(6) << endl;
    cout << "Enter a number: ";
    int a;
    cin >> a;
    cout << "Run time factorial of " << a << ": " << factorial(a) << endl;
 
See also this for more nice examples. See this and this for further discussion. Multiline strings
        const char* code = R"--(
          printf("foo\tbar\n");
          return 0;
        )--";
See this. C++ memory management protip RAII: Resource Acquisition Is Instantiation This is not new in C++11, but in my experience I have rarely seen it mentioned in C++ learning material, and it does make a huge difference in my code. See this and this for details. Constructors and member initializer lists Initializers in curly braces now have their own type: std::initializer_list:
#include <string>
#include <iostream>
#include <unordered_set>
using namespace std;
// std::initializer_list< >
//   will have as its value all the elements inside the curly braces
string join(initializer_list<string> strings)
 
    string res;
    for (auto str: strings)
     
        if (!res.empty())
            res += ", ";
        res += str;
     
    return res;
 
int main()
 
    unordered_set<string> blacklist  ".", "..", ".git", ".gitignore"  ;
    cout << join(  "antani", "blinda"  ) << endl;
 
See this for details, including the new uniform initialization trick of omitting parentesis in constructors so that you can call normal constructors and initializer_list constructors with the same syntax, which looks like an interesting thing when writing generic code in templates. Type inference I can now use auto instead of a type to let the compiler automatically compute the value of something I assign to:
        auto i = 3 + 2;
        // See also https://github.com/esseks/monicelli
        vector<string> names  "antani", "blinda", "supercazzola"  ;
        for (auto i = names.cbegin(); i != names.cend(); ++i)
            cout << i;
        template<typename T>
        T frobble(const T& stuff)
         
             // This will work whatever type is returned by stuff.read()
             auto i = stuff.read();
             //  
         
See this for more details. Range-based for loop C++ now has an equivalent of the various foreach constructs found in several interpreted languages!
        for (auto i: list_of_stuff)
                cout << i << endl;
        for (auto n:  0,1,2,3,4,5 )
                cout << n << endl;
        // This construct:
        for (auto i: stuff)
        // If stuff is an array, it becomes:
        for (i = stuff, i < stuff + sizeof(stuff) / sizeof(stuff[0]); ++i)
        // If stuff has .begin() and .end() methods it becomes:
        for (i = stuff.begin(); i != stuff.end(); ++i)
        // Otherwise it becomes:
        for (i = begin(stuff); i != end(stuff); ++i)
        // And you can define begin() and end() functions for any type you
        // want, at any time
See this and this for details. Lambda functions and expressions Lambdas! Closures! Something like this:
// JavaScript
var add = function(a, b)   return a + b;  
# Python
add = lambda a, b: a + b
Becomes this:
auto add = [](int a, int b)   return a + b;  
And something like this:
// JavaScript
var a = 0;
$.each([1, 2, 3, 4], function(idx, el)   a += el  );
Becomes this:
unsigned a = 0;
std::for_each(  1, 2, 3, 4  , [&a](int el)   return a += el;  );
See this, this and this. Tuple types C++ now has a std::tuple type, that like in Python can be used to implement functions that return multiple values:
        tuple<int, string, vector<string>> parse_stuff()
         
                return make_tuple(id, name, values);
         
        string name; vector<string> values;
        // std::ignore can be used to throw away a result
        tie(ignore, name, values) = parse_stuff();
        // std::tie can also be used to do other kind of
        // multi-operations besides assignment:
        return tie(a, b, c) < tie(a1, b1, c1);
        // Is the same as:
        if (a != a1) return a < a1;
        if (b != b1) return b < b1;
        return c < c1;
See here, here and here. Regular expressions We now have regular expressions!
        std::regex re(R"((\w+)\s+(\w+))");
        string s("antani blinda");
        smatch res;
        if (regex_match(s, res, re))
            cout << "OK " << res[1] << " -- " << res[2] << endl;
The syntax is ECMAScript by default and can be optionally changed to basic, extended, awk, grep, or egrep. See here and here. General-purpose smart pointers There is std::unique_ptr to code memory ownership explicitly, and std::shared_ptr as a reference counted pointer, and smart pointers can have custom destructors:
    unique_ptr<dirent, std::function<void(void*)>> dirbuf((dirent*)malloc(len), free);
See here and here. Miscellaneous other cool things Standard attribute specifiers
string errno_str(int error)
 
    char buf[256];
#if (_POSIX_C_SOURCE >= 200112L   _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
    strerror_r(errno, buf, 256);
    string res(buf);
#else
    string res(strerror_r(errno, buf, 256));
#endif
    return res;
 
[ [noreturn]] void throw_libc_error(int error)
 
    throw runtime_error(errno_str(error));
 
See here. Hash tables See here and look at the new containers unordered_set, unordered_map, unordered_multiset, and unordered_multimap. Multithreading There is a standard threading model, with quite a bit of library support: see here, here, here, and here for atomic data structures. Variadic templates Templates can now take variable number of arguments, and that opens possibilities for interesting code generation, like implementing a generic, type-safe printf statement, or something like this:
db.query(R"(
   INSERT INTO table NAMES (id, name, description)
     VALUES (?, ?, ?)
)", 4, "genio", "fantasia, intuizione, decisione, e velocit  di esecuzione");
See here and here. Essential tools You need at least g++ 4.8 or clang 3.3 to have full C++11 support. They will be both available in jessie, and for wheezy you can use the nightly clang packages repository. I cannot think of a good excuse not to use -Wall on new code. scan-build from clang is another nice resource for catching even more potential problems at compile time. valgrind is a great tool for runtime code analysis: valgrind --tool=memcheck (the default) will check your program for wrong memory accesses and memory leaks. valgrind --tool=callgrind will trace function calls for profiling, to be analyzed with kcachegrind. valgrind --tool=helgrind can check multi-threaded programs for suspicious concurrent memory accesse patterns. And of course gdb: a nice trick with C++ is to issue catch throw to get a breakpoint at the point where an exception is being thrown. help catch provides a list of other interesting catch examples. Coredump tips: ulimit -c to enable core dumps, triggering a core dump with ^\, opening a core with gdb program core, and more details on man 5 core. An extra gdb tip, which is not related to C++ but helped me considerably recently, is that it can be attached to running python programs to get a live Python traceback.

28 December 2011

Paul Tagliamonte: libolla (from the useless script department)

Hello, World! Today s hacks come remotely, on the first day of my long trek to Cleveland. As many debian readers know, debian URLs are usually transmitted over IRC or email with some snappy abbreviations. Usually, you ll see something like:
Feel free to check out information about frob at wiki.d.o/Frob
or something like:
I have uploaded package bar onto mentors.d.n for review
What bugs me most about this is that I have to expand URLs by hand. Which is lame. Enter libolla (a fitting name as well as a graceful nod to my alma mater John Carroll University s crest). When LD_PRELOAD d, it ll intercept and expand calls to getaddrinfo transparently. It seems to work fine on SSH, and chrome (but I can t test well, since I m not on a real line). This was all hacked up in a few hours I had to spare, and without any sort of internet love, so I m willing to bet there are some bits that can be cleaned up (after all, the name of the blog is Peace, Love and C++ , not Peace, Love and C - I don t clam to be a c expert ;) ) So, feel free to fork the project on github (or as I can now do - http://g.c/paultag/libolla) Now, I just need to find a way to globally pre-load this for apps that I start in my DE. Should be easy enough fiddling with some env-var files.

8 December 2011

Tanguy Ortolo: Return codes

According to Eric S. Raymond, one rule for Unix programming is the Rule of Silence: When a program has nothing surprising to say, it should say nothing. Since return codes are a form of information, I would like to add: when a program has carried out its task with no surprise, it should exit(0).Take xscreensaver-command -lock, for instance. That command is meant to make a running XScreenSaver to lock the screen. I have never seen it fail in doing so, however I sometimes get a non-zero code:
% xscreensaver -lock
xscreensaver-command: could not frobnicate window 4212
zsh: exit 1   xscreensaver-command -lock
Well, xscreensaver-command, I have the deep regret to announce you that despite of your surprising return code, you successfully succeeded to lock my screen. But that return code is wrong and annoying. Wrong, because as a user, I do not care if xscreensaver-command -lock failed to frobnicate some window he would have loved to as long as it does its job and locks my screen. To the user's point of view, locking the screen is binary: either it is done and it is a success or it is not done and that is a failure. And it is annoying, because it makes the return code meaningless and prevents you from using it to do things like:
% # Lock screen and suspend to RAM (only if locking was successful)
% xscreensaver -lock && sudo pm-suspend
With xscreensaver-command sometimes returning a non-zero code with no apparent reason, you end with a locked screen and your computer still running, and have to unlock it and try again. This looks like this meaningless dialogue: So please, when you write a utility, design your return code for the user, not for you. If your utility has done the job, it should exit(0). What happened inside does may interest you as the developer but it does not matter to the user as long as the job is done, so it should not be reported to him, especially not with a misleading failure code.

8 February 2011

Jonathan McDowell: My Squeeze upgrade notes

I did my first upgrade of a lenny box to squeeze today; a test server in work. All went pretty smoothly but I had a handful of things I had to frob manually that I thought I'd write up here: I think that's pretty smooth overall; kudos to all those involved. I've a few more boxes to upgrade, but they're all more likely to have people complaining at me if there are hiccups so they'll have to wait until I have a suitable block of time set aside.

14 September 2010

Kees Cook: my part in the ecosystem

I was asked to write about what I do at Canonical and what I do in the Free Software community at large. There is obviously a great deal of overlap, but I ll start with the things I m involved with when I m wearing my Ubuntu hat. My primary job at Canonical is keeping Ubuntu secure. This means that I, along with the rest of the Ubuntu Security Team, coordinate with other Free Software distributions and upstream projects to publish fixes together so that everyone in the community has the smallest possible window of vulnerability, no matter if they re running Ubuntu, Debian, RedHat/Fedora, SUSE/openSUSE, Gentoo, etc. Between vendor-sec, oss-security, and the steady stream of new CVEs, there is plenty going on. In addition to updates, the Security Team works on pro-active security protections. I work on userspace security hardening via patches to gcc and the kernel, and via build-wrapper script packages. Much of this work has been related trying to coordinate these changes with Debian, and to clean up unfinished pieces that were left unsolved by RedHat, who had originally developed many of the hardening features. Things like proper /proc/$pid/maps permissions, real AT_RANDOM implementation, upstreaming executable stack fixing patches, upstreaming kernel NX-emu, etc. Most of the kernel work I ve done has gotten upstream, but lately some of the more aggressive protections have been hitting frustrating upstream roadblocks. Besides the hardening work, I also improve and support the AppArmor Mandatory Access Control system, as well as write and improve confinement profiles for processes on Ubuntu. This work ends up improving everyone s experience with AppArmor, especially now that it has gotten accepted upstream in the Linux kernel. I audit code from time to time, both on the clock with Canonical and in my free time. I m no Tavis Ormandy, but I try. ;) I ve found various security issues in Xorg, Koffice, smb4k, libgd2, Inkscape, curl+GnuTLS, hplip, wpa_supplicant, Flickr Drupal module, poppler/xpdf, LimeSurvey, tunapie, and the Linux kernel. With my Canonical hat off, I do all kinds of random things around the Free Software ecosystem. I m a sysadmin for kernel.org. In Debian, I maintain a few packages, continue to try to push for security hardening, and contribute to the CVE triage efforts of the Debian Security Team. I ve written or maintain several weird projects, including MythTVFS for browsing MythTV recordings, GOPchop for doing non-encoding editing of MPEG2-PS streams, Perl s Device::SerialPort module, and the TAP paging server Sendpage. For a selection of things I ve contributed to other project, I ve implemented TPM RNG access in rng-tools, made contributions to Inkscape s build and print systems, implemented CryptProtect for Wine, wrote a PayPal IPN agent in PHP that actually checks SSL certificates unlike every other implementation I could find, added additional protocol-specific STARTTLS negotiations to OpenSSL, implemented the initial DVD navigation support in MPlayer, updated serial port logic in Scantool for communicating with vehicle CAN interfaces, tried to add support for new types of timeouts in Snort and Ettercap, fixed bugs in mutt, and added HPUX audio support to the Apple ][ emulator XGS. As you can see, I like making weird/ancient protocols, unfriendly file formats, and security features more accessible to people using Free Software. I ve done this through patches, convincing people to take those patches, auditing code, testing fixes and features, and doing packaging work. When I go to conferences, I attend UDS, DefCon, OSCon, and LinuxCon. I ve presented in the past at OSCon on various topics including security, testing, and video formats, and presented at the Linux Security Summit (miniconf before LinuxCon this year) on the need to upstream various out-of-tree security features available to the Linux kernel. I love our ecosystem, and I love being part of it. :)

29 November 2009

Jonathan McDowell: DIY laptop SSD "upgrade"

I'm due a new laptop; my Portege R200 is over 4 years old now, I find it much slower than my desktop (no surprise; P-M 1.2GHz/1.2GB vs Core 2 2GHz/4GB), it's had a new battery and it has an annoying whine on the screen unless you press the side in just the right way. It's still better for long periods of use than my EEE 901, which is why I keep it. In particular I'm off to LCA2010 in January, along with some associated travel beforehand, and I'll want more than the EEE for that, but probably not a brand new laptop. Which meant that when the R200 started throwing disk errors recently I wasn't particularly happy.

Having decided it wasn't worth buying a new 1.8" drive I looked for alternatives. eBay offered plenty of options for 1.8" IDE to CF adaptors and I picked up a Kingston 32GB CF card from eBuyer. I copied across the data from the old drive using a USB adaptor, frobbed grub sufficiently that I got it installed on the CF, then swapped out the drive for the adaptor + CF. I had to do the swap a few times; the first I forgot to have a kernel with ext2 support (the HDD was ext3, but I went back to ext2 for the CF). The second I'd done my usual trick of forgetting to populate /dev with things like console and sda* (ie enough to get to the point where udev will run). And then grub needed some prodding to boot without intervention. I got there in the end and I'm currently writing this from said laptop.

I've made a few changes to the Debian install in an attempt to make things smoother; basically the same tricks people have been using on EEEs or other slow SSD devices. No swap, Iceweasel synchronous toolkit writes disabled, filesystems mounted with noatime, /tmp on tmpfs, various daemons that I don't really use disabled. It's still noticably slower than with the HDD, particularly on writes. However it's quieter and as long as it lasts for the next 3 months I'm happy (plus after that I can reuse the 32G CF card somewhere else, which I couldn't have done with a 1.8" HDD as easily).

Now, back to eying the Lenovo X200s (ugly, trackpoint but 1440x900 display, good battery life) and Toshiba R600 (slower, lower res but pretty and trackpad).as potential replacements. Maybe there'll be something even shinier in 12" by next year...

21 May 2009

Josselin Mouette: Reporting useful bugs

Here are a few hints if you want your reports to be treated more promptly. When testing fails, try unstable If you are running testing, not all bug reports are interesting. More specifically, the relevant ones are about insufficient dependencies that let slip into testing a non-working combination of packages. Think of the I upgraded foo, then bar broke category. Otherwise, the reason why reportbug looks for newer versions of a package in unstable is that, in most cases, the bug is fixed in unstable. If you can, always try the unstable version before reporting the bug. Report bugs against the failing package This is related to printing in a GNOME program, so I report this against libgnomeprint. Always file reports against the failing program. If there is a library involved, reportbug will include the necessary information so that the maintainer can easily reassign. If you re not sure of the affected package, use a metapackage (for example, gnome for GNOME-related packages). Do not second-guess the origin of the bug After upgrading libfoo, bar starts crashing, so I m reporting it against libfoo. Unless you can tell which function is at fault and how this is ABI breakage, you should report the bug against the program that crashes. The program s maintainer will reassign if needed, and will hit the library s maintainer with a hammer if needed. Don t forget to explain what s wrong The frobniz in libfrob is broken, you should change /usr/share/libfrob/blah line 13 to something else. I don t know what libfrob is about, but I have some problems that look frobniz-related. Do not second-guess, always start explaining what bug you are seeing first. Your attempts at investigating it can be interesting, but don t forget to explain what bug lead you on investigating. What is the use case we should cover? I m trying to do that with your package and it looks extremely complicated/doesn t work as expected/fails miserably. Your package is clearly broken! If your attempts to do something that should be trivial, given the purpose of the package, fail, then you are probably looking at the problem at the wrong angle. There may be a much simpler, though radically different, way to do what you are trying to achieve. In these situations, always include in your report what you are trying to do and why you want to do it. strace is not a general-purpose debugging tool Whether you observe a crash, a deadlock or a livelock, strace is not the tool that will give us information. The only thing you do by adding a strace log to the bug report is making it unreadable with its thousands of lines of output. For the specific cases that require strace for debugging, these traces are welcome but if you re not sure, don t attach them. The developers will ask them for you. Otherwise, the general-purpose debugging tool is gdb. Use reportbug There is a good reason why some packages include bug control files and scripts. Use a reporting tool that takes them into account. Unless you are requesting an enhancement, always use reportbug. Please avoid reportbug-ng since it only provides parts of the required information.

8 June 2008

Robert McQueen: Xen virtual interfaces with more than one IP

I’ve got a load of boxes running Debian etch with Xen 3.0.3 with routed networking (rather than bridged, so I can do iptables and reverse path filtering etc in dom0). Since upgrading from Xen 2.x many moons ago, I’ve not known how to configure one virtual interface to have more than one IP. In the meantime, I’ve ended up doing nonsense like providing a VM with two interfaces just to give it two IPs. However, this interacts really badly with reverse path filtering unless you do a bunch of source-routing rocket science in the domU to send out through the right vif. So, I looked at the vif-route script and it seems to support iterating through a space-separated list of IPs, but I was totally unable to find any documentation or mailing list posts explaining how to format the IPs within the formerly-Python key/value Xen domain config file syntax. After a while playing with the parser and various levels of quoting, I found that actually, the correct amount of quoting is none at all, and also uncovered a bug in another script which prevents it from working correctly. In the hope that this might help others using Google and trying to achieve the same as me, here is my recipe for configuring Xen vif devices to have multiple IPs (note that I think this might be specific to Xen 3.0.x, as I believe 3.2.x introduces config files in the S-expression format which is what xenstore uses internally):
  1. Configure your VM using this surprisingly obvious, but somewhat dubious syntax (including a second argument just to prove that yes, it really does work like that):

    vif=['ip=1.2.3.4 5.6.7.8, mac=00:16:3e:01:23:45']

    When parsed into SXP by xm create, this sets the ip value correctly as a space separated list as the scripts expect:

    (device (vif (ip '1.2.3.4 5.6.7.8') (mac 00:16:3e:01:23:45)))
  2. Fix the bug in /etc/xen/scripts/vif-common.sh:

    --- /etc/xen/scripts/vif-common.sh~ 2008-06-09 01:14:23.065065119 +0100
    +++ /etc/xen/scripts/vif-common.sh 2008-06-09 01:11:06.599986274 +0100
    @@ -103,7 +103,7 @@
    if [ "$ip" != "" ]
    then
    local addr
    - for addr in “$ip”
    + for addr in $ip
    do
    frob_iptable -s “$addr”
    done
  3. Set up multi-homed or aliased interfaces as normal in the domU (depending if you’re a ip or an ifconfig kinda guy).
  4. Profit!

20 May 2008

Andrew Pollock: [debian] Etch and a half

I thought I'd throw the Etch and a half kernel on my laptop, mainly because I wanted better better battery performance, which I suspected I'd get (and powertop would work). So far, all I've noticed is
apollock@frobnitz:~$ sudo iwlist eth1 scan 1>/dev/null
Warning: Driver for device eth1 has been compiled with version 22
of Wireless Extension, while this program supports up to version 20.
Some things may be broken...
It seems the appropriate people are already aware of it, and it's purely cosmetic.

3 August 2007

Joey Hess: vm party line

Say you have a virtual machine at one of the larger hosting companies. You're sharing a system with some unknown number of other users. Wouldn't it be nice to be able to chat with people from the other VMs on the machine? Assume that the hosting company doesn't particularly want you do to this; they prefer you don't know that the machine's CPU is split 30 ways and that you're migrated to a new, random machine every night at 3 am. I wonder how to accomplish this? The coolest hack would be to frob some kind of available on-machine data source that the other users could watch. This basically requires finding and exploiting a minor security hole, though. Maybe a centralised registry would be better, if there's some way to uniquely identify a given host machine from inside the VM. Focusing on xen, I think enough data is leaked to make this possible. This should at least narrow it down to a set of similar boxes at a given hosting company, and then you can start looking at the network..
On a not-unrelated note, this diversidial system is way cool. 300 baud via telnet! I especially like the use of an ipod as a tape drive for booting the Apple IIe.

25 May 2007

Jonathan McDowell: Thoughts on calendars

I keep having what I've started to think of as the "calendar conversation" with various people. I start by outlining what I think are some fairly reasonable requirements. I'd like to have multiple calenders viewable by different sets of people. So Simon would be able to view my work calendar, while Katherine could see my personal calender (and possibly small bits of work calender where I was going to be away from home). I also want to be able to view my calenders from a variety of devices. My desktop, my phone and my laptop, for example. A web interface might be nice too, though less important to me. This doesn't seem like a lot to ask. My general hope is that whoever I'm boring about this will then say "Oh, you need to look at foo and maybe bar". After all, that's the case with most software related things I need - it's already been done, and there's a good solution available. What actually happens is the person I'm talking to nods in agreement and says they'd like the same sort of things but don't know of anything that manages it. I think the problem comes down to syncing. Sharing my calendars with other people is effectively allowing them to sync their calendar(s) with mine, with some sort of filtering so we each see only what the other wants to see. Likewise, multiple devices is all about syncing. Changes made via one method need to be visible on all of them (ideally as soon as possible). Decent syncing also brings another advantage; client independence. If I can reliably sync my information to a variety of devices/clients then I can try a different client with little risk. We have this already for mail - anything that can talk POP3, IMAP and/or mbox is easy to try out and if you don't like it then you can just change back to what you had before or try something else. Calendaring doesn't seem to have that. I don't think that the interface a client exposes needs to be complex. At a basic level what you need is a way to find out what the client thinks has been added, removed or changed. You also need to present this information in a standard format. Unfortunately iCal (RFC2445) appears to be what we've got here. I think it's a bit overly inclusive, which seems to lead to incomplete implementations. Is there a complete iCal parser library out there? The best hope for syncing that I'm aware of is OpenSync. And I haven't been that impressed; while I managed to get it to move the contacts from my SonyEricsson v600i to my Nokia E70 some of the details got mangled on the way. And lack of things like recurring event support in some of the plugins (eg the Google Calendar syncing adaptor) or warnings about data loss in the Sunbird plugin aren't encouraging. Speaking of Sunbird, I'm not impressed. Last time I looked (and it doesn't appear to have moved very far since then) it didn't make any attempt to support syncing. I'm sorry, WebDAV isn't a syncing system. It's a way of storing files remotely. Sure, I found the interface ok, but I need to make my calendaring data accessible for it to be useful. The Windows approach to all of this seems to be ActiveSync and the use of Outlook. I don't believe that it really handles more than the desktop client and a remote device though? And group calendar sharing requires an Exchange server? Not exactly the flexible solution I'm looking for. I think a key point is that all of this needs to be reliable. I didn't spend time debugging my OpenSync contact syncing issues partly because I didn't notice straight away that there was a problem (it was with additional details like email addresses rather than names/numbers IIRC), but also because it was a lot of work to delve into the code and find out just what on earth was going on. A while back I started looking at writing some calendar syncing code (called Pony) and hit a problem with complete inconsistency in handling time zones between clients that put me right off. If it's not reliable it's not useful. If it's not useful people won't test it and fix it. I think a starting point is a reliable iCal implementation that can handle everything in the spec. From there you can write plugins that will take whatever bastardised variant your device/client supports and translate to and from it. The syncing tool will need to keep a master copy of all the data, because there's no guarantee anything else will be able to support all the fields. A local complete copy should enable appropriate frobbing of data to/from any device/client without losing the information if a new device/client that can handle the data is added. Of course almost all the above applies to contacts as well; I have work contacts, personal contacts, boring house contacts (plumber, garage etc). vCard is the appropriate interchange format for that (why did vCalendar become iCalendar, but vCard not change?), but contacts feature similar issues to calendars I believe. Does this seem reasonable? Please tell me someone has already done it. Point me at Debian packages that will let me sync my phone, my Google Calendar and a local client and make me very happy. I have visions of a suite of tools all chatting over DBus; a little client that looks for my phone to appear over bluetooth and then syncs when it does, a little client that monitors Google Calendar for changes. Sunbird reporting when something changes (and accepting notification of changes). Some other client ([Dates http://www.pimlico-project.org/dates.html]?) doing the same. Another sending the data over WebDAV or SFTP so that my laptop can pick up the info when I'm on the move. I don't think I'm the only person looking for this sort of stuff. Where is it?

31 March 2006

Norbert Tretkowski: Music player

I switched to orpheus a while ago, but it lacks last.fm support. A friend told me he's quite happy with amarok, so I decided to give it a try. But I didn't like it. Then I installed mpd, ncmpc and mpdscribble. That's exactly what I wanted.

3 February 2006

Jonathan McDowell: Friday fun with consumer routers

I'm such a funster. It's Friday night and I've spent it fighting with consumer routers in an attempt to get my home setup sorted out a bit. And I've made some progress, but it's taken a while. My old setup was an Asus WL-500g with a USB Speedtouch attached. This was running a hacked up version of Oleg's firmware, with kernel 2.4.20 (ewwwww) and the userland Speedtouch pppoa3 driver. It's been up 253 days as I type, which is quite impressive IMO. The plan was to get something else doing the same job so that I could try and get more up to date firmware on the Asus (probably OpenWRT) and give it to my parents as a wireless access point / print server. First try was my Netgear DG834G. Unfortunately the ADSL interface on it doesn't want to sync to the line for any length of time. I don't really want to faff with it at present, so I gave up on that. I do want to try and get this sorted, as it has a native ADSL interface, but the AR7Port appears to have stagnated a bit. Next was the Netgear WGT634U. I'd built an OpenWRT image for this and tried to flash it earlier in the week, but messed it up and bricked the router. So opened it up, hooked a serial console up and managed to restore it easily enough. A little bit of frobbing and I had it recognising the Speedtouch. Result. This has a 2.6.15.1 kernel, which means in kernel driver goodness and nice and up to date. Plus OpenWRT makes it easy to add various nicities like radvd and dnsmasq. I'm currently using this solution and will keep an eye on it over the weekend before reinstalling the Asus. Of course my home network has become simplified a bit by the fact I no longer factor the NTL connection into it. That's always just been a backup thing since getting ADSL from Black Cat (mmmm, IPv6 goodness) and I've decided to finally ditch it soon. However I might want to add a modem to the WGT634U at some point - probably using a USB serial dongle I guess, as I don't think the internal ports do hardware flow control. That's a battle for another day though. I also managed to get rid of a whole load of computer junk that was working but unused, thanks to Norfolk FreeCycle. Kathy will be pleased when she comes back from London tomorrow. :)

31 December 2005

Jonathan McDowell: It's good to be back.

I finally had my first flight cancelled on me yesterday. I suppose given that I've been flying a few times a year for at least the past 8 years (even if it's only back and forth to Northern Ireland) I should consider myself lucky. I arrived at Belfast City Airport at about 8am, for a 9:45am flight (the last time I flew from Belfast we hit really bad traffic, so we ended up overcompensating). On check in I discovered it was delayed by 15 minutes. Shortly after I'd made my way through security it was delayed by 45 minutes. Then they delayed it until midday. Then at 11:30 they said they'd have an announcement at midday. And then at 11:45 they cancelled it. Now, I was flying from Belfast to Norwich. There's only one such flight a day. So I'm a bit stuck. And by the time I get to the front of the refunds queue they've filled up the flight today (Saturday), leaving me the option of a direct flight to Norwich on Sunday, or any other flight leaving Belfast City on Friday that they have seats on. So I go to London Gatwick, supposed to leave at 14:30. And it gets delayed by 45 minutes straight after I check in. Thankfully it does actually take off at 15:15 and I manage to get to England. On the wrong side of London for Norwich, but hey, the trains are running. I negotiate the Gatwick Express, get a tube to Liverpool Street and get on a train to Norwich. Which then gets delayed for 25 minutes because a train breaks down in front of it. Bah. I finally get home just after 9pm, rather than the 11:30am or so I would have managed if my initial flight had taken off on time. The house is still in one piece, the plants haven't died, I have food again. Rar. And I know this is small fry compared to American flight horror stories, or the potential problems we could have had when Uncle Steve lost our clothes en route to Brazil, but it's the first time I've had a major problem with flights. (We'll ignore the fun I had when turning on my desktop machine and seeing "GRUB Read Error" displayed. Damn scanner had decided to frob the SCSI bus enough that the BIOS could boot grub but grub couldn't then see sda.)

29 December 2005

Decklin Foster: lastfmsubmitd

Apparently, tis the season to be writing your own Last.fm plugin. So here is mine. I finally got fed up with finding and causing bugs in mpdscribble (I am a bad sponsor!) it s written in C with libsoup, blah blah, can t stand C, and so I revived the MPD pseudo-listener I had started on as a replacement for that awful orphaned cacheless one-off we were all using before mpdscribble. I also fixed a few issues that were bugging me, like failing to detect restarts and tag changes. Not wanting to muddy up any of that logic with HTTP gar, I decided to write a separate program to queue, cache and send along song submissions. They re two or three hundred lines of Python each, and single-threaded (yes, that means child writers blocking and hanging around if the network code is in the middle of timing out or backing off. Deal with it! This is UNIX). I m pretty happy with the design, although the implementation is still very rough. This also mimics the model they want to move to for player plugins in general, which is good, because it will be less work for me to implement version 2.0 of the protocol once that is finalized. Additionally, I was able to find a more satisfying way to solve the disconnected-CD-player problem than my previous dreadful method of either using a few kludgey scripts to frob around in my primary plugin s cache or dealing with using cdscrobbler and having to be very careful about one plugin not stepping on the other s toes and invalidating my backlog. So this is the second example program included. (Oh yes, that part uses the Python bindings for MusicBrainz. MB is awesome. The Python bindings are hideous, however straight port of the C++ API. I d probably be better off just dumping the RDF into a real RDF implementation and doing my own cross-referencing, instead of prying it out piecemeal with select queries and non-polymorphic getters and all the other absolute nonsense you have to deal with when writing in a language without high-level data types or garbage collection. But regardless of implementation woes, this has kept me close to the MB metadata for my favorite CDs, and so I ve been busy all week entering and voting on mods (and doing research to justify my changes), which is very satisfying. I have yet to begin the gargantuan task of adding MB tags to my Ogg collection (I know, this is really just a matter of babysitting tp_tagger, but I ve got some work cut out for me to even get to that point).) And of course, once this becomes less prototypey, anyone who likes it can knock all the networking code out of their plugin and use it as their system service . Perhaps if I m agile enough this can become official code! It is at least a mootable proof-of-concept that UNIX systems don t necessarily need a heavyweight libscrobbler to abstract the service stuff out of the player plugin. I won t get my hopes up though. Still a bit unsure about the name. Theoretically it seems the service (you know, the thing we pay money to if we like it) should be Last.fm, while the software and protocols should still be Audioscrobbler, but the distinction does not seem to be drawn very clearly in practice. With the analogous situation of livejournal vs. ljcom you had a grokkable technical delineation (different repositories) as well as other widely used installations besides ljcom (DeadJournal, etc). I really can t see there ever being a competing installation of Audioscrobbler, because licensing the streamables is a formidable investment hurdle, and there s a negative market effect (also, the web site is not open source). But I am also bored of just sticking scrobble onto something else, so I wanted to grab sticking last onto something else before it got old. I haven t the faintest clue what makes me prefer whimsical names for some projects and prosaic ones for others. Note to actual MPD users (all, like, 5 of you): the stuff in the package will not handshake at the moment, as I have not yet gotten Russ to bless the client ID I made up. Will try to catch him tomorrow. Or later today I suppose. It s ready to go now. Next up: Because it s either this or Sound Juicer, I think perhaps it s time to bid adieu to abcde and write a MusicBrainz plugin for jack (jack is nice enough, I just haven t had a truly compelling reason to switch, and there have always been lots of good eyeballs on abcde). FreeDB delenda est.

4 December 2005

Clint Adams: glibc wackiness

I don't know which is scarier, strfry() or memfrob().

24 November 2005

Clint Adams: Musical Personality Disorder

Decklin, MPD looks pretty interesting. I have filed a wishlist bug on vux on the presumption that integrating it with mpd would be peachy keen. Still, mpdscribble is conspiring against me. That it can't get MusicBrainz IDs is a minor irritation. The more significant problem is that it doesn't work at all. For every song, it whines about skipping, like this:
new song detected (Leonard Cohen - Hey, That's No Way to Say Goodbye)
skipping detected, not submitting.
I'm not doing any skipping, and crossfade is set to '0'. I continue to use my happy NIH pseudosolution.

Next.