netselect (0.3.ds1-14) direct (non packaging) changes

Summary

 Makefile        |   22 +++---
 README          |   13 +--
 netselect-apt   |  197 +++++++++++++++++++++++++++++++++++++++++---------------
 netselect-apt.1 |   85 ++++++++++++++++++++++++
 netselect.1     |  123 ++++++++++++++++++++++++++++++++++
 netselect.c     |   55 ++++++++++++---
 6 files changed, 421 insertions(+), 74 deletions(-)

    
download this patch

Patch contents

--- netselect-0.3.ds1.orig/netselect-apt
+++ netselect-0.3.ds1/netselect-apt
@@ -1,10 +1,10 @@
 #!/bin/bash
 #
 # A script to create an apt sources.list file automatically by downloading
-# the list of Debian mirrors and choosing the fastest main and non-us server
-# using netselect.
+# the list of Debian mirrors and choosing the fastest using netselect.
 #
 # Author: Avery Pennarun <apenwarr@debian.org>
+# Enhancements: Filippo Giunchedi <filippo@esaurito.net>
 #
 # License: public domain.  Please feel free to improve this script.  It
 # doesn't really belong in the netselect package, particularly since the
@@ -13,18 +13,33 @@
 # please do.  Then tell me, so I can remove it from the netselect package.
 #
 # TO DO:
-#   - parse command line options for output file, input files, etc.
 #   - have some way to pass options (especially -t) to netselect.
 #   - test the generated files automatically.  Some mirrors in the list
 #       are broken.  We should at least verify that the Packages and Sources
 #       files exist and aren't ancient.
 #   - maybe generate redundant entries, in case one server is missing files?
-#
-#
 
-URL="http://www.debian.org/mirror/mirrors_full"
-DISTRO="$1"
+# our defaults
+# RATIONALE for WANT_SOURCES and WANT_NONFREE environmental variables:
+# both variables can be system wide and can be useful to not always specify
+# them on the commandline
+
+want_sources=${WANT_SOURCES:-0}
+want_nonfree=${WANT_NONFREE:-0}
+want_security=1
+infile=""
+tmpinfile="1"
+outfile="sources.list"
+distro="stable"
+protocol="HTTP"
+url="http://www.debian.org/mirror/mirrors_full"
+arch=$(/usr/bin/dpkg-architecture -qDEB_HOST_ARCH)
+
+options="-o a:si:o:nfhu -l arch:,sources,infile:,outfile:,nonfree,ftp,help"
+
+trap '[ "$tmpinfile" = "1" ] && rm -f "$infile"' TERM INT EXIT
 
+# misc functions
 log()
 {
 	echo "$@" >&2
@@ -33,73 +48,155 @@
 run_netselect()
 {
 	SEARCH="$1"
+	PROTO="$2"
+	out=$(netselect -v -s 1 $(cat "$infile" \
+		| perl -n -e '
+			$/="<br><br>";
+			while(<>){
+				next if $_ !~ /Site:/;
+				if( ( /Includes architectures:.+'"$arch"'.+/i ||
+						$_ !~ /Includes architectures:/ ) &&
+						m@<br>'"$SEARCH"':.*<a href="('"$PROTO"'://.*?)">@i
+					){
+					print("$1\n");
+				}
+			}'))
+	rv=$?
+	echo $out | awk '{print $2}'
+	return $rv
+}
 
-	netselect -v -s 1 $(cat mirrors_full \
-	    | perl -n -e '
-	    	if (m{^'"$SEARCH"':.*<a href="(http://.*?)">}) {
-			print("$1\n");
-		}') \
-	    | awk '{print $2}'
+netselect_generic_error()
+{
+	log "netselect was unable to find a mirror, this probably means that"
+	log "you are behind a firewall and it is blocking traceroute."
 }
 
-if [ -z "$1" ]; then
-	log "You didn't provide a distribution name (usually 'stable', "
-	log "'testing', or 'unstable') on the command line.  We'll use "
-	log "'stable' by default."
-	log
-	DISTRO=stable
+netselect_permission_error()
+{
+	log "netselect was unable to operate successfully, please check the errors,"
+	log "most likely you don't have enough permission."
+}
+
+usage()
+{
+	log "Usage: netselect-apt [OPTIONS] [ debian_release ]"
+	log "       debian_release is one of stable, testing, unstable, experimental"
+	log "       or a codename etch, lenny, squeeze, sid"
+	log "Options:"
+	log "   -a, --arch ARCH        Use mirrors containing arch ($arch)"
+	log "   -s, --sources          Include deb-src lines in generated file (no)"
+	log "   -i, --infile INFILE    Use INFILE as the input file (temp file)"
+	log "   -o, --outfile OUTFILE  Use OUTFILE as the output file (sources.list)"
+	log "   -n, --nonfree          Use also non-free packages in OUTFILE (no)"
+	log "   -f, --ftp              Use FTP as the protocol for OUTFILE (HTTP)"
+}
+
+
+# commandline parsing
+temp=$(getopt $options -n 'netselect-apt' -- "$@")
+if [ $? != 0 ]; then echo "Terminating..." >&2; exit 2; fi
+eval set -- "$temp"
+while true; do
+	case "$1" in
+		-a|--arch) arch=$2; shift 2 ;;
+		-s|--sources) want_sources=1; shift ;;
+		-i|--infile) infile="$2"; tmpinfile="0"; shift 2 ;;
+		-o|--outfile) outfile="$2"; shift 2 ;;
+		-n|--nonfree) want_nonfree=1; shift ;;
+		-f|--ftp) protocol="FTP"; shift ;;
+		-h|--help) usage; exit 0;;
+		--) shift; break;;
+		*) echo "Internal Error!"; echo "args: $@"; exit 1;;
+	esac
+done
+
+# distro is a non-option for backward compatibility
+case "$1" in
+	# don't forget to update the usage with new codenames
+	stable|testing|unstable|experimental|etch|lenny|squeeze|sid) distro="$1" ;;
+	'') ;;
+	*) log "Invalid distribution: $1"; exit 1 ;;
+esac
+
+if [ "$distro" != "stable" ]; then
+	want_security=0
 fi
 
-if [ ! -f mirrors_full -a ! -e /usr/bin/wget ]; then
+# netselect starting
+log "Using distribution $distro."
+
+if [ "$tmpinfile" = "0" -a ! -f "$infile" -a ! -x /usr/bin/wget ]; then
 	log "Sorry, this script requires the 'wget' package in order to run."
-	log "You can also download the mirrors list yourself and leave it"
-	log "in the current directory:"
-	log "        $URL"
-	exit 1
+	log "You can also download the mirrors list yourself and pass it"
+	log "with -i option, consult the manpage for further details:"
+	log "        $url"
+	exit 2
 fi
 
-if [ ! -f mirrors_full ]; then
+if [ ! -f "$infile" ]; then
+	if [ "$tmpinfile" = "1" ]; then
+		infile=$(mktemp -t netselect-apt.XXXXXX) ||
+			{ log "unable to create tempfile"; exit 2; }
+	fi
+
 	log "Retrieving the list of mirrors from www.debian.org..."
 	log
 
-	if ! wget "$URL"; then
+	if ! /usr/bin/wget -O "$infile" "$url"; then
 		log "$0: wget failed.  Please try to correct the problem"
 		log "by reading the wget messages printed above."
 		exit 2
 	fi
 else
-	log "There is a already a mirrors_full file in the current"
-	log "directory.  I'll use that, rather than downloading it again."
+	log "$infile has been found."
+	log "I'll use that, rather than downloading it again."
 	log
 fi
 
 log "Choosing a main Debian mirror using netselect."
-MAIN=$(run_netselect "Packages over HTTP")
-log "The fastest server seems to be:"
-log "        $MAIN"
-log
-
-log "Choosing a non-US Debian mirror using netselect."
-NON_US=$(run_netselect "Non-US packages over HTTP")
-log "The fastest non-US server seems to be:"
-log "        $NON_US"
-log
+main=$(run_netselect "Packages over $protocol" $protocol)
+netselect_rv=$?
+if [ $netselect_rv -eq 0 ]; then
+	log "The fastest server seems to be:"
+	log "        $main"
+	log
+elif [ $netselect_rv -eq 6 ]; then
+	netselect_permission_error
+	exit 2
+else
+	netselect_generic_error
+	exit 2
+fi
 
-log "Writing the sources.list in the current directory."
+log "Writing $outfile."
 
-rm -f sources.list
+if [ -f "$outfile" ]; then
+	destfile="$outfile.$(date +%s)"
+	log "$outfile exists, moving to $destfile"
+	mv $outfile $destfile
+fi
+
+sections="main contrib"
+if [ "$want_nonfree" -eq 1 ]; then sections="$sections non-free"; fi
 
 (
-	echo "# the main Debian packages.  Uncomment the deb-src line if you"
-	echo "# want 'apt-get source' to work with most packages."
-	echo "deb $MAIN $DISTRO main contrib non-free"
-	echo "# deb-src $MAIN $DISTRO main contrib non-free"
-	
+	echo "# Debian packages for $distro"
+	echo "deb $main $distro $sections"
+	echo "# Uncomment the deb-src line if you want 'apt-get source'"
+	echo "# to work with most packages."
+	if [ "$want_sources" -eq 0 ]; then
+		echo -n "# "
+	fi
+	echo "deb-src $main $distro $sections"
+
 	echo
-	echo "# the non-US Debian packages.  Uncomment the deb-src line if you"
-	echo "# want 'apt-get source' to work with non-US packages."
-	echo "deb $NON_US $DISTRO/non-US main contrib non-free"
-	echo "# deb-src $NON_US $DISTRO/non-US main contrib non-free"
-) >sources.list
+	echo "# Security updates for stable"
+	if [ "$want_security" -eq 0 ]; then
+		echo -n "# "
+	fi
+	echo "deb http://security.debian.org/ stable/updates $sections"
+
+) > $outfile
 
 echo "Done."
--- netselect-0.3.ds1.orig/netselect.c
+++ netselect-0.3.ds1/netselect.c
@@ -1,6 +1,6 @@
 /*
  * Netselect:
- *      Copyright (c) 1998-2001 by Avery Pennarun <apenwarr@worldvisions.ca>
+ *      Copyright (c) 1998-2001 by Avery Pennarun <apenwarr@nit.ca>
  *
  * Traceroute:
  * Copyright (c) 1990, 1993
@@ -151,18 +151,27 @@
     extern char *optarg;
     extern int optind;
     int hostcount, startcount, endcount = 0, sent_one, lag, min_lag = 100;
-    int ch, seq, ttl, max_ttl = 30, min_tries = 10, num_score = 1;
+    int ch, seq, ttl, max_ttl = 30, num_score = 1;
+    unsigned int min_tries = 10;
     struct timeval now;
     struct timezone tz;
     OPacket outpacket;          /* last output (udp) packet */
     HostData *host, *hosts;
     int numhosts, delay, must_continue, count;
+    int socket_errno = 0;
+
+    /* we might have cap_net_raw on linux, instead print a tip if and when
+       sendto fails
+    if (geteuid () != 0)
+        fprintf (stderr, "%s: root privileges required\n", argv[0]);
+    */
 
     if ((rcvsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0
      || (sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW )) < 0)
     {
-	perror("netselect: socket");
-	return 5;
+	/* Capture errno so that command-line options can be parsed.
+	   We delay reporting an error until this has happened. */
+	socket_errno = errno;
     }
 
     /* drop root privileges as soon as possible! */
@@ -218,7 +227,19 @@
 	usage();
 	return 1;
     }
-    
+
+    /* Was there an error acquiring a socket? */
+    if (socket_errno)
+    {
+	errno = socket_errno;
+	perror("netselect: socket");
+	if (errno == EPERM) {
+		fprintf(stderr, "You should be root to run netselect.\n");
+		return 6;
+	}
+	return 5;
+    }
+
     memset(&outpacket, 0, sizeof(OPacket));
     outpacket.ip.ip_tos = 0;
     outpacket.ip.ip_v = IPVERSION;
@@ -407,6 +428,19 @@
 {
     HostData *host;
     
+    if (addr)
+    {
+      int hcount;
+      for (hcount = 0, host = hosts; hcount < *numhosts; hcount++, host++)
+	if (host->addr.sin_addr.s_addr == addr->sin_addr.s_addr)
+	{
+	  if (verbose >= 1)
+	    fprintf(stderr, "\nDuplicate address %s (%s, %s); keeping only under first name.\n",
+		    inet_ntoa(addr->sin_addr), host->hostname, hostname);
+	  return hosts;
+	}
+    }
+    
     (*numhosts)++;
     
     if (!hosts)
@@ -549,7 +583,7 @@
 		result.addr.sin_family = AF_INET;
 		result.addr.sin_addr.s_addr = inet_addr(names[count]);
 		
-		if (result.addr.sin_addr.s_addr != -1)
+		if (result.addr.sin_addr.s_addr != INADDR_NONE)
 		{
 		    write(pipes[1], &result, sizeof(result));
 		}
@@ -775,7 +809,7 @@
 #if !defined(__GLIBC__)
     int fromlen = sizeof(from);
 #else				/* __GLIBC__ */
-    size_t fromlen = sizeof(from);
+    socklen_t fromlen = sizeof(from);
 #endif				/* __GLIBC__ */
 
     FD_ZERO(&fds);
@@ -846,7 +880,8 @@
 	    
 	    if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
 		up->uh_sport == htons(ident) &&
-		up->uh_dport == htons(port + host->seq))
+		up->uh_dport == htons(port + host->seq) &&
+		hip->ip_dst.s_addr == host->addr.sin_addr.s_addr)
 	    {
 		host->code = (type == ICMP_TIMXCEED ? -1 : code + 1);
 		return host;
@@ -873,8 +908,8 @@
 static void usage(void)
 {
     fprintf(stderr,
-	    "Usage: netselect [-v] [-vv] [-t min_tries] [-m max_ttl]"
-	    " host [host...]\n");
+	    "Usage: netselect [-v|-vv|-vvv] [-m max_ttl] [-s servers] "
+	    "[-t min_tries] host ...\n");
 }
 
 
--- netselect-0.3.ds1.orig/README
+++ netselect-0.3.ds1/README
@@ -36,10 +36,8 @@
 nothing got through at all.  That indicates that either the host doesn't
 exist, or it is down.
 
-For a bigger example, I've included the file debian-ftp-mirrors, which is a
-partially up-to-date list of Debian Linux FTP site mirrors.  Try this:
-
-	netselect -vvv $(cat debian-ftp-mirrors)
+For a bigger example, try netselect-apt to build your own sources.list for apt
+with the (possibily) fastest debian mirror.
 
 
 But Why?
@@ -53,7 +51,7 @@
 its scoring mechanism.  If you want, however, you can still pass the raw
 results and score the servers as you like.  Try this, for example:
 
-	netselect -vv -s 0 $(cat debian-ftp-mirrors)
+	netselect -vv -s 0 $(cat <your_list_of_sites>)
 	
 The "-s 0" option disables printing of scores at the bottom of the list, and
 "-vv" enables printing of the statistics.
@@ -103,6 +101,9 @@
 	-vvv	-- very very verbose mode.  Everything -vv prints, plus
 		   print every packet received as it happens.  Good for
 		   debugging or trying to figure out how it works.
+	
+	-vvvv   -- very very very verbose mode. Everything -vvv prints,
+		   plus a trace of all packets sent.
 		   
 	-m #	-- maximum ttl.  Don't accept hosts with more hops than
 		   this.
@@ -133,4 +134,4 @@
 This program is highly experimental.  Please let me know what you think.
 
 	- Avery Pennarun
-	  <apenwarr@worldvisions.ca>
+	  <apenwarr@nit.ca>
--- netselect-0.3.ds1.orig/Makefile
+++ netselect-0.3.ds1/Makefile
@@ -1,6 +1,6 @@
 PREFIX = /usr/local
 BINDEST = ${PREFIX}/bin
-MANDEST = ${PREFIX}/man/man8
+MANDEST = ${PREFIX}/man/man1
 
 CC = gcc
 CFLAGS = -O2 -Wall -I. -g
@@ -20,23 +20,29 @@
 
 netselect: netselect.o
 	${CC} ${LDFLAGS} -o $@ $^ ${LIBS}
+
+install: $(PROG)
+	
 ifdef OS2
 	emxbind -bwq netselect
 else
-	-sudo chown root netselect && sudo chmod u+s netselect
+	chown root netselect && chmod u+s netselect
 endif
-
-install: $(PROG)
+	
 	-install -d ${BINDEST}
-	#-install -d ${MANDEST}
-	install $(STRIP) -o root -g root -m 4755 \
+	-install -d ${MANDEST}
+	install -o root -g root -m 4755 \
 		netselect${BINSUFFIX} ${BINDEST}
 	install -o root -g root -m 0755 netselect-apt ${BINDEST}
-	#install -o root -g root -m 0644 netselect.8 ${MANDEST}
+	install -o root -g root -m 0644 netselect.1 ${MANDEST}
+	install -o root -g root -m 0644 netselect-apt.1 ${MANDEST}
 
+	
 uninstall:
 	$(RM) ${BINDEST}/netselect${BINSUFFIX} ${BINDEST}/netselect-apt
-	$(RM) ${MANDEST}/netselect.8
+	$(RM) ${MANDEST}/netselect.1
+	$(RM) ${MANDEST}/netselect-apt.1
 
 clean:
 	$(RM) netselect netselect${BINSUFFIX} *.o *~ build-stamp core
+	$(RM) mirrors_full
--- netselect-0.3.ds1.orig/netselect.1
+++ netselect-0.3.ds1/netselect.1
@@ -0,0 +1,123 @@
+.TH NETSELECT 1 "March 14, 2004" "DEBIAN" \" -*- nroff -*-
+.\" Please adjust this date whenever revising the manpage.
+
+.SH NAME
+netselect \- choose the fastest server automatically
+
+.SH SYNOPSIS
+
+.B netselect
+.RB [ \|\-v\| | \|\-vv\| | \|\-vvv\| | \|\-vvvv\| ]
+.\".RB [ \|\-vv\| ]
+.RB [ \|\-m
+.IR HOPS ]
+.RB [ \|\-s
+.IR SERVERS\| ]
+.RB [ \|\-t
+.IR PACKETS\| ]
+.IR host \ ...
+
+.SH DESCRIPTION
+
+.B netselect
+determines several facts about all of the hosts given on the command
+line, much faster than you would if you manually tried to use
+.B ping
+and
+.BR traceroute .
+
+For each
+.IR host ,
+.B netselect
+figures out the approximate
+.B ping
+time (though not as accurately as
+.B ping
+does), the number of network "hops" to
+reach the target, and the percentage of
+.B ping
+requests that got through successfully. Then
+.B netselect
+calculates the "score" of each operational
+.I host 
+based on these values.  A lower score is better, in the end it prints
+one line showing the server with the best score.
+
+.SH EXAMPLES
+
+.nf
+\fB#\fR netselect \-vv ftp.fceia.unr.edu.ar ftp.kulnet.kuleuven.ac.be \\
+		 ftp.cdrom.com ftp.debian.org ftp.de.debian.org
+.fi
+
+This is the output:
+
+.nf
+ftp.fceia.unr.edu.ar         2792 ms  23 hops  100% ok ( 1/ 1) [ 9213]
+ftp.kulnet.kuleuven.ac.be    9999 ms  30 hops    0% ok
+ftp.cdrom.com                  94 ms   8 hops  100% ok (10/10) [  169]
+ftp.debian.org                 46 ms  15 hops  100% ok (10/10) [  115]
+ftp.de.debian.org            9999 ms  30 hops    0% ok
+  115 ftp.debian.org
+.fi
+
+The value in brackets is the "score" of each operational host based on these
+values.  A lower score is better.  The last line shows the server with the
+best score.  If we had not used '\-vv' on the command line, only this last
+line would have been printed.
+
+Note that for ftp.kulnet.kuleuven.ac.be and ftp.de.debian.org in this case,
+nothing got through at all.  That indicates that either the host doesn't
+exist, or it is down.
+
+.SH OPTIONS
+.TP
+.B \-v
+Verbose mode.  Displays nameserver resolution messages to stderr.  You
+probably want this so that you don't get bored waiting for a hundred
+name resolutions to finish.
+
+.TP
+.B \-vv
+Very verbose mode.  Displays nameserver resolution and statistics (not
+just scores) to STDERR and STDOUT.
+
+.TP
+.B \-vvv
+Very very verbose mode.  Everything \-vv prints, plus it print every
+packet received as it happens.  Good for debugging or trying to figure
+out how it works.
+
+.TP
+.B \-vvvv
+Very very very verbose mode.  Everything \-vvv prints, plus a trace of
+all packets sent.
+
+.TP
+.BI \-m\  HOPS
+Maximum TTL (time to live).  Don't accept hosts that are further than
+.I HOPS
+away.
+
+.TP
+.BI \-s\  SERVERS
+Print this many "top-scoring"
+.I SERVERS
+at the end of the list.  If
+.I SERVERS
+is 0, then this disables printing of high scores.
+
+.TP
+.BI \-t\  PACKETS
+Make sure at least 50% of the hosts get tested with this many
+.IR PACKETS .
+The more packets you use, the more accurate are the results... and the
+longer it takes to run.  The default is 10, which is usually okay.
+
+.SH SEE ALSO
+.BR ping (8),
+.BR traceroute (8),
+.BR netselect-apt (1).
+
+.SH AUTHOR
+Avery Pennarun <apenwarr@nit.ca>
--- netselect-0.3.ds1.orig/netselect-apt.1
+++ netselect-0.3.ds1/netselect-apt.1
@@ -0,0 +1,85 @@
+.TH NETSELECT-APT 1 "March 6, 2008" "DEBIAN" \" -*- nroff -*-
+.\" Please adjust this date whenever revising the manpage.
+
+.SH NAME
+netselect-apt \- create sources.list for the fastest Debian mirrors
+
+.SH SYNOPSIS
+.B netselect-apt
+.RI [ OPTIONS ]
+.\" copied verbatim from netselect-apt
+.RI [ \|stable | testing | unstable | experimental | \fIrelease_codename\fR | sid ]
+
+.SH DESCRIPTION
+
+.B netselect-apt
+automatically creates a \fIsources.list\fR file for using with
+.BR apt
+for the specified distribution by downloading the list of Debian
+mirrors using
+.B wget
+and choosing the fastest servers using
+.BR netselect .
+The output file is written to
+.IR OUTFILE .
+
+If
+.BI "\-i" " INFILE"
+is passed
+.B netselect-apt
+uses that rather than downloading another copy to a temporary file. The file
+will be downloaded from http://www.debian.org/mirror/mirrors_full
+
+.SH OPTIONS
+.TP
+.IR stable | testing | unstable | experimental | \fIrelease_codename\fR | sid
+Specify which distribution of Debian to use.  By default
+.I stable
+is used.
+.TP
+.BI "\-a, \-\-arch" " ARCH"
+Use mirrors containing \fIARCH\fR. By default the architecture of the current
+machine is used as reported by \fBdpkg\fR
+.TP
+.B \-s, \-\-sources
+While generating
+.I OUTFILE
+include also deb-src lines to use with ``apt-get source'' to obtain
+Debian source packages.
+.TP
+.BI "\-i, \-\-infile" " INFILE"
+Use
+.I INFILE
+instead of downloading the mirror list to a temporary file. The file must be in
+the same format as mirrors_full.
+.TP
+.BI "\-o, \-\-outfile" " OUTFILE"
+Use
+.I OUTFILE
+instead of sources.list.
+.TP
+.B \-n, \-\-nonfree
+Include also non-free section while generating
+.IR OUTFILE .
+.TP
+.B \-f, \-\-ftp
+Use FTP mirrors instead of HTTP and generate
+.I OUTFILE
+accordingly.
+
+.SH ENVIRONMENT
+.TP
+.B WANT_SOURCES
+setting this to 1 is equivalent to --sources
+.TP
+.B WANT_NONFREE
+setting this to 1 is equivalent to --nonfree
+
+.SH SEE ALSO
+.BR netselect (1),
+.BR wget (1),
+.BR apt (8),
+.IR sources.list (5).
+
+.SH AUTHOR
+Avery Pennarun <apenwarr@nit.ca>