summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDexter Morgan <dmorgan@mageia.org>2011-06-02 20:51:35 +0000
committerDexter Morgan <dmorgan@mageia.org>2011-06-02 20:51:35 +0000
commita9b2bdafaf625d10aef2f476aa4014fd36c846bc (patch)
tree2364afc0ee6739b59a25c44d68c9f003bcaf03d9 /tools
downloaddrakx-backup-do-not-use-a9b2bdafaf625d10aef2f476aa4014fd36c846bc.tar
drakx-backup-do-not-use-a9b2bdafaf625d10aef2f476aa4014fd36c846bc.tar.gz
drakx-backup-do-not-use-a9b2bdafaf625d10aef2f476aa4014fd36c846bc.tar.bz2
drakx-backup-do-not-use-a9b2bdafaf625d10aef2f476aa4014fd36c846bc.tar.xz
drakx-backup-do-not-use-a9b2bdafaf625d10aef2f476aa4014fd36c846bc.zip
Branch for updates
Diffstat (limited to 'tools')
-rw-r--r--tools/.perl_checker10
-rw-r--r--tools/Makefile27
-rwxr-xr-xtools/checkusedmodules22
-rwxr-xr-xtools/drakx-in-chroot228
-rw-r--r--tools/extractchangelog2
-rwxr-xr-xtools/get-needed-drakx-modules19
-rwxr-xr-xtools/hd_grub.cgi102
-rwxr-xr-xtools/install-xml-file-list383
-rw-r--r--tools/make_lang_png_transparent.c167
-rwxr-xr-xtools/mdkinst_stage2_tool66
-rw-r--r--tools/ntp_servers.pl303
-rw-r--r--tools/rpcinfo-flushed.c740
-rw-r--r--tools/serial_probe/Makefile13
-rw-r--r--tools/serial_probe/device.h104
-rw-r--r--tools/serial_probe/kudzu.h26
-rw-r--r--tools/serial_probe/serial.c1136
-rw-r--r--tools/serial_probe/serial.h43
-rw-r--r--tools/serial_probe/serial_probe.c114
-rw-r--r--tools/shift_all.pl113
-rw-r--r--tools/shift_img.c165
-rwxr-xr-xtools/simplify-drakx-modules5
-rwxr-xr-xtools/specific_arch9
-rw-r--r--tools/xhost+.c11
23 files changed, 3808 insertions, 0 deletions
diff --git a/tools/.perl_checker b/tools/.perl_checker
new file mode 100644
index 000000000..8dc1d2d7d
--- /dev/null
+++ b/tools/.perl_checker
@@ -0,0 +1,10 @@
+AutoLoader
+Carp::Heavy
+constant
+Cwd
+Digest::base
+Encode
+File::Path
+Gtk2::Gdk::Keysyms
+IO::Handle
+Pod::Usage \ No newline at end of file
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 000000000..669b6f987
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,27 @@
+DIRS = serial_probe
+CFLAGS = -Wall
+
+ARCH := $(shell arch | egrep "(x86_64|sparc64|s390x)")
+ifneq ("x$(ARCH)", "x")
+LIB_NAME = lib64
+else
+LIB_NAME = lib
+endif
+
+.PHONY: clean install $(DIRS)
+
+all: $(DIRS) xhost+ rpcinfo-flushed
+
+$(DIRS):
+ make -C $@
+
+install:
+ install -d $(ROOTDEST)/misc
+ install mdkinst_stage2_tool drakx-in-chroot $(ROOTDEST)/misc
+
+xhost+: %: %.c
+ $(CC) $(CFLAGS) $< -L/usr/X11R6/$(LIB_NAME) -lX11 -o $@
+
+clean:
+ for i in $(DIRS); do $(MAKE) -C $$i clean; done
+ rm -rf *~ xhost+ rpcinfo-flushed */*.o
diff --git a/tools/checkusedmodules b/tools/checkusedmodules
new file mode 100755
index 000000000..433ed54d9
--- /dev/null
+++ b/tools/checkusedmodules
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# This script compares the perl modules used by the .pm files in perl-install
+# against the ones listed in share/list, to detect potential missing modules
+# (and potential run-time problems during the stage 2)
+
+cd ../perl-install || exit 1;
+
+# list of used .pm files
+find . -name '*.pm' -not -name b_dump_strings.pm -not -path ./interactive/http.pm | \
+ xargs perl -lne '/^\s*(use|require)\s+([\w:]+)/ && print $2' | sort -u > /tmp/gi-used-pm
+
+# list of .pm files included in install
+perl -lne 'm{/(?:PERL_VERSION|ARCH-linux|vendor_perl/\*)/([\w/]+)\.pm$} and $_=$1, s,/,::,g, print' share/list > /tmp/gi-found-pm0
+find . -name blib -prune -o -name '*.pm' | perl -ne 's,^\./,,; s/\.pm$// or next; s,/,::,g; print' >> /tmp/gi-found-pm0
+
+# compute difference
+sort -u /tmp/gi-found-pm0 > /tmp/gi-found-pm
+diff -u /tmp/gi-{used,found}-pm | perl -lne 'BEGIN{print"Unpackaged modules:"} s/^-(?!-)/ / && print'
+
+# cleanup
+rm -f /tmp/gi-used-pm /tmp/gi-found-pm{,0}
diff --git a/tools/drakx-in-chroot b/tools/drakx-in-chroot
new file mode 100755
index 000000000..a4064ed5b
--- /dev/null
+++ b/tools/drakx-in-chroot
@@ -0,0 +1,228 @@
+#!/usr/bin/perl
+
+use MDK::Common;
+
+my $SLASH_LOCATION = '/tmp/drakx-in-chroot';
+
+my $verbose = 0;
+my $prefix_ROOTED = '/mnt';
+my $IMAGE_LOCATION_ROOTED = '/tmp/image';
+my $MEDIA_LOCATION_ROOTED = '/tmp/media';
+my $STAGE2_LOCATION_ROOTED = '/tmp/stage2';
+my $LOOP_MOUNT_POINT = "$SLASH_LOCATION/tmp/loop";
+my $LIVE_LOCATION_REL = 'install/stage2/live/';
+my $COMPRESSED_LOCATION_REL = 'install/stage2/';
+my $COMPRESSED_FILE_REL = $COMPRESSED_LOCATION_REL . 'mdkinst.sqfs';
+my $AUTO_INSTALL_ROOTED = '/tmp/auto_inst.cfg.pl';
+my $DEFCFG_ROOTED = '/tmp/defcfg.pl';
+my $RPMSRATE_ROOTED = '/tmp/rpmsrate';
+my $resolution = '800x600';
+my ($disk_iso_repository, $repository_uri);
+
+@ARGV >= 2 or die "usage: drakx-in-chroot <root of distrib> <dir to install to> [options]\n
+\nOptions specific to drakx-in-chroot:
+ --flang XX use XX locale
+ --disk-iso path of a distro
+ --resolution=XXXxYYYY (eg: --resolution=1024x768)\n
+ --repository=<path> path of packages repository
+ --text text mode installer
+";
+
+(my $repository, my $dir, @ARGV) = @ARGV;
+foreach (@ARGV) {
+ if (/--resolution=(.*)/) {
+ $resolution = $1;
+ } elsif (/--disk-iso=(.*)/) {
+ $disk_iso_repository = $1;
+ } elsif (/--repository=(.*)/) {
+ $repository_uri = $1;
+ }
+}
+my ($repository_without_arch, $repository_arch) = basename($repository) eq arch() ? (dirname($repository), '/' . arch()) : ($repository, '');
+my $STAGE2_LOCATION = $SLASH_LOCATION . $STAGE2_LOCATION_ROOTED;
+
+my $sudo;
+if ($>) {
+ $sudo = "sudo";
+ $ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";
+}
+
+undef $ENV{TMPDIR}; # prevent packdrake faillure on creating temporary files
+
+if (-d $SLASH_LOCATION) {
+ umount_all() == 0 or exit(1);
+ sys("$sudo rm -rf $SLASH_LOCATION/var/lib/rpm $SLASH_LOCATION/dev/mapper");
+ rm_rf($SLASH_LOCATION);
+}
+
+mkdir_p("$SLASH_LOCATION$_") foreach '/dev', '/dev/usb', '/etc', '/var', '/proc', '/sys', $STAGE2_LOCATION_ROOTED, $MEDIA_LOCATION_ROOTED, $prefix_ROOTED;
+
+sys("$sudo rm -rf $dir") if $ENV{CLEAN};
+-e $dir or sys("$sudo mkdir -p $dir");
+
+copy_auto_install_files();
+
+my $remote_repository = $repository =~ m!^(ftp|http)://! && $1;
+if ($remote_repository) {
+ my $local_mdkinst = "$SLASH_LOCATION/tmp/mdkinst.sqfs";
+ sys("curl --silent -o $local_mdkinst $repository/$COMPRESSED_FILE_REL");
+ mount_mdkinst($local_mdkinst);
+} elsif (-d "$repository/$LIVE_LOCATION_REL") {
+ sys("$sudo mount -o bind $repository/$LIVE_LOCATION_REL $STAGE2_LOCATION");
+} elsif (-e "$repository/$COMPRESSED_FILE_REL") {
+ mount_mdkinst("$repository/$COMPRESSED_FILE_REL");
+}
+
+sys("$sudo mount -o bind $dir $SLASH_LOCATION$prefix_ROOTED");
+$repository_uri ||= $repository_without_arch if !$remote_repository;
+sys("$sudo mount -o bind $repository_uri $SLASH_LOCATION$MEDIA_LOCATION_ROOTED") if $repository_uri;
+
+sys("$sudo mount -t proc none $SLASH_LOCATION/proc");
+sys("$sudo mount -t sysfs none $SLASH_LOCATION/sys");
+
+if ($disk_iso_repository) {
+ my $repository_arch = $repository_arch || 'i586';
+ mkdir_p($LOOP_MOUNT_POINT);
+ sys("$sudo mount -o loop,ro $disk_iso_repository $LOOP_MOUNT_POINT");
+ symlinkf('loop/' . $repository_arch, "$SLASH_LOCATION$IMAGE_LOCATION_ROOTED"); # FIXME: arch()
+}
+
+symlinkf('media' . $repository_arch, "$SLASH_LOCATION$IMAGE_LOCATION_ROOTED");
+create_initial_symlinks();
+create_initial_devices();
+
+apply_stage2_updates();
+
+output("$SLASH_LOCATION/etc/hosts", "127.0.0.1 localhost\n") if ! -e "$SLASH_LOCATION/etc/hosts";
+
+#- in the chroot, we have no way to know which device corresponds to the "/" partition.
+#- so helping it by giving the device which provide major/minor information
+mkdir_p("$dir/dev");
+eval { cp_af($_, "$dir$_") } foreach qw(/dev/root);
+
+#- if the DISPLAY is remote, we may need to resolve the name:
+eval { cp_af($_, "$SLASH_LOCATION$_") } foreach qw(/etc/resolv.conf);
+
+{
+ chomp(my $kernel_version = `uname -r`);
+ my $dir = "/modules/$kernel_version";
+ mkdir_p("$SLASH_LOCATION$dir");
+ output_p("$SLASH_LOCATION$dir" . $_, "\n") foreach "/lib/$dir/modules.dep", "/lib/$dir/modules.alias";
+}
+
+my $Xnest_pid;
+my $Xnest_bin = find { whereis_binary($_) } 'Xephyr', 'Xnest';
+if (!-f ($SLASH_LOCATION . $AUTO_INSTALL_ROOTED) && $Xnest_bin && (join('', @ARGV) !~ /--text/)) {
+ my $DISPLAY = ':8';
+ $Xnest_pid = fork();
+ if (!$Xnest_pid) {
+ exec $Xnest_bin, $DISPLAY, '-ac', ($Xnest_bin eq 'Xephyr' ? '-screen' : '-geometry'), $resolution or die "Xnest failed\n";
+ }
+ $ENV{DISPLAY} = '127.0.0.1' . $DISPLAY;
+}
+
+if (my $pid = fork()) {
+ waitpid $pid, 0;
+ umount_all() == 0 or warn "umounting failed\n";
+ $Xnest_pid and kill 15, $Xnest_pid;
+} else {
+ $ENV{TERM} = 'linux'; # we only have terminfo for terminal "linux"
+ $ENV{HOME} = '/';
+ # to kept sync with gi/mdk-stage1/init.c::env:
+ $ENV{LD_LIBRARY_PATH}='/lib:/usr/lib:/mnt/lib:/mnt/usr/lib:/usr/X11R6/lib:/mnt/usr/X11R6/lib:/lib64:/usr/lib64:/usr/X11R6/lib64:/mnt/lib64:/mnt/usr/lib64:/mnt/usr/X11R6/lib64';
+ if ($remote_repository) {
+ $ENV{URLPREFIX} = $repository;
+ }
+ my $cmd = join(' ', "/usr/bin/runinstall2 --local_install",
+ if_($disk_iso_repository, "--method disk-iso"),
+ if_($remote_repository, "--method $remote_repository"),
+ @ARGV);
+ exec "$sudo chroot $SLASH_LOCATION $cmd" or die "exec $cmd in $SLASH_LOCATION failed\n";
+}
+
+sub system_verbose { warn join(' ', @_), "\n" if $verbose; system(@_) }
+sub sys { &system_verbose; $? and die qq(running "@_" failed: $?\n) }
+
+sub mount_mdkinst {
+ my ($mdkinst) = @_;
+ sys("$sudo mount -t squashfs -o loop,ro $mdkinst $STAGE2_LOCATION");
+}
+sub create_initial_symlinks() {
+ foreach (cat_or_die("$STAGE2_LOCATION/usr/share/symlinks")) {
+ my ($from, $to_) = split;
+ my $to = $SLASH_LOCATION . ($to_ || $from);
+ $from = "$STAGE2_LOCATION_ROOTED$from" if !$to_;
+ if (! -l $to) {
+ symlink $from, $to or die "symlinking $to failed\n";
+ }
+ }
+}
+
+sub create_initial_devices() {
+ sys("$sudo cp -a /dev/{mem,null,random,urandom} $SLASH_LOCATION/dev");
+}
+
+sub umount_all() {
+ my $err;
+ clean_stage2_updates();
+ my @procs = ('/proc/bus/usb', '/proc', '/sys');
+ foreach ((map { "$prefix_ROOTED$_" } @procs, ''), @procs, $STAGE2_LOCATION_ROOTED, $LOOP_MOUNT_POINT, $MEDIA_LOCATION_ROOTED, $IMAGE_LOCATION_ROOTED) {
+ my $dir = "$SLASH_LOCATION$_";
+ rmdir $dir;
+ if (-d $dir) {
+ if (m!/proc/bus/usb! || begins_with($_, $prefix_ROOTED)) {
+ system_verbose "$sudo umount $dir 2>/dev/null";
+ next;
+ }
+ system_verbose "$sudo umount $dir";
+ }
+ rmdir $dir;
+ if (-d $dir) {
+ warn "$dir is busy\n";
+ $err++;
+ }
+ }
+ if (my @remaining = cat_('/proc/mounts') =~ m!($SLASH_LOCATION/mnt/\S+)!g) {
+ warn "umount those mount points first: ", join(' ', @remaining), "\n";
+ $err++;
+ }
+ $err;
+}
+
+sub copy_auto_install_files() {
+ my ($opt);
+ each_index {
+ if ($opt eq 'auto_install' && -f $_) {
+ cp_f($_, $SLASH_LOCATION . $AUTO_INSTALL_ROOTED);
+ $_ = $AUTO_INSTALL_ROOTED;
+ } elsif ($opt eq 'defcfg' && -f $_) {
+ cp_f($_, $SLASH_LOCATION . $DEFCFG_ROOTED);
+ $_ = $DEFCFG_ROOTED;
+ } elsif ($opt eq 'rpmsrate' && -f $_) {
+ cp_f($_, $SLASH_LOCATION . $RPMSRATE_ROOTED);
+ }
+ undef $opt;
+ /^--?(.*)/ and $opt = $1;
+ } @ARGV;
+}
+
+my @stage2_updates;
+sub apply_stage2_updates() {
+ each_index {
+ if ($_ eq '--stage2-update') {
+ my $file = $ARGV[$::i+1];
+ my $dest = $ARGV[$::i+2];
+ if (-f $file && $dest) {
+ undef $_;
+ undef $ARGV[$::i+1];
+ undef $ARGV[$::i+2];
+ push @stage2_updates, $dest;
+ sys("$sudo mount --bind $file $STAGE2_LOCATION/$dest");
+ }
+ }
+ } @ARGV;
+}
+
+sub clean_stage2_updates() {
+ sys("$sudo umount $STAGE2_LOCATION/$_") foreach @stage2_updates;
+}
diff --git a/tools/extractchangelog b/tools/extractchangelog
new file mode 100644
index 000000000..d838a0b68
--- /dev/null
+++ b/tools/extractchangelog
@@ -0,0 +1,2 @@
+#!/usr/bin/perl
+
diff --git a/tools/get-needed-drakx-modules b/tools/get-needed-drakx-modules
new file mode 100755
index 000000000..019820c04
--- /dev/null
+++ b/tools/get-needed-drakx-modules
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+use MDK::Common;
+
+my ($rel, $dest, $script) = @ARGV;
+
+$rel =~ s!/?$!!;
+
+foreach (`strace -efile perl -cw -I $rel $script 2>&1`) {
+ my ($f) = /^open\("(.*?)",.*\)\s*=\s*\d+$/ or next;
+ $f !~ m!/usr/lib/perl5/[^/]*/warnings.pm! or next;
+ if (begins_with($f, $rel)) {
+ print $f, "\t", $dest . substr($f, length($rel)), "\n";
+ } elsif (begins_with($f, '/dev/')) {
+ # skip
+ } elsif (begins_with($f, '/')) {
+ print "$f\n";
+ }
+}
diff --git a/tools/hd_grub.cgi b/tools/hd_grub.cgi
new file mode 100755
index 000000000..ac55b6eaf
--- /dev/null
+++ b/tools/hd_grub.cgi
@@ -0,0 +1,102 @@
+#!/usr/bin/perl
+
+use CGI ':all';
+use CGI::Carp;
+
+my $default_append = "ramdisk_size=128000 root=/dev/ram3";
+my $default_acpi = "acpi=ht";
+my $default_vga = "vga=788";
+
+my $cgi_name = "/" . ($0 =~ m|([^/]+)$|)[0];
+
+print
+ header(),
+ start_html(-TITLE => 'hd_grub configuration');
+
+if (param()) {
+ print_menu_lst();
+} else {
+ print_form();
+}
+
+print end_html;
+
+
+sub menu_lst {
+ my ($hd, $hd_linux, $partition_number, $directory) = @_;
+
+ my $grub_partition_number = $partition_number - 1;
+
+ <<EOF;
+timeout 0
+default 0
+
+title Mageia Install
+
+root ($hd,$grub_partition_number)
+kernel $directory/isolinux/alt0/vmlinuz $default_append $default_acpi $default_vga automatic=method:disk,partition:$hd_linux$partition_number,directory:$directory
+initrd $directory/isolinux/alt0/all.rdz
+EOF
+
+}
+
+sub print_menu_lst {
+ my $directory = param('directory');
+ $directory =~ s!^/!!;
+ print
+ ol(li(qq(Select the text below and save it in a file "menu.lst")),
+ li(qq(Create a floppy from $directory/images/hd_grub.img (eg: <tt>dd if=hd_grub.img of=/dev/fd0</tt>))),
+ li(qq(Copy the file "menu.lst" to the floppy, overwriting the existing one)),
+ ),
+ p(),
+ start_form(-name => 'form', -action => $cgi_name, -method => 'get'),
+ textarea(-default => menu_lst(param('hd'), param('hd_linux'), param('partition_number'), "/$directory"),
+ -rows => 15, -columns => 120,
+ ),
+ end_form(),
+}
+
+sub print_form {
+ print
+ p(),
+ start_form(-name => 'form', -action => $cgi_name, -method => 'get'),
+ ul("Please choose the partition where %s is copied.",
+ li(popup_menu(-name => "hd", -default => 'hd0',
+ -values => [ 'hd0' .. 'hd3' ],
+ -labels => { hd0 => '1st BIOS hard drive (usually hda or sda)',
+ hd1 => '2nd BIOS hard drive',
+ hd2 => '3rd BIOS hard drive',
+ hd3 => '4th BIOS hard drive',
+ })),
+ li(popup_menu(-name => "hd_linux", -default => 'hda',
+ -values => [ 'hda' .. 'hdd', 'sda' .. 'sdc', 'hde' .. 'hdh' ],
+ -labels => {
+ hda => '1st IDE hard drive (hda)',
+ hdb => '2nd IDE hard drive (hdb)',
+ hdc => '3rd IDE hard drive (hdc)',
+ hdd => '4th IDE hard drive (hdd)',
+ hde => '5th IDE hard drive (hde)',
+ hdf => '6th IDE hard drive (hdf)',
+ hdg => '7th IDE hard drive (hdg)',
+ hdh => '8th IDE hard drive (hdh)',
+ sda => '1st SCSI hard drive (sda)',
+ sdb => '2nd SCSI hard drive (sdb)',
+ sdc => '3rd SCSI hard drive (sdc)',
+ })),
+ li(popup_menu(-name => "partition_number", -default => '0',
+ -values => [ 1 .. 15 ],
+ -labels => { 1 => '1st primary partition (hda1, sda1 or ...)',
+ 2 => '2nd primary partition',
+ 3 => '3rd primary partition',
+ 4 => '4th primary partition',
+ 5 => '5th partition (hda5, sda5 or ...) (first logical partition)',
+ map { $_ => $_ . 'th partition' } 6 .. 15
+ })),
+ ),
+ p(),
+ ul("Please enter the directory containing the %s Distribution (relative to the partition chosen above)",
+ li(textfield(-name => 'directory', -default => '/cooker/i586', size => 40)),
+ ),
+ p(submit(-name => 'Go')),
+ end_form();
+}
diff --git a/tools/install-xml-file-list b/tools/install-xml-file-list
new file mode 100755
index 000000000..56b7a0a4f
--- /dev/null
+++ b/tools/install-xml-file-list
@@ -0,0 +1,383 @@
+#!/usr/bin/perl
+
+use FileHandle;
+use MDK::Common;
+use XML::Parser;
+use Data::Dumper;
+use File::Glob;
+use Config;
+use Cwd 'cwd';
+
+my $want_sudo = $ARGV[0] eq '--sudo' && shift @ARGV;
+
+@ARGV == 2 or die "usage: install-xml-file-list [--sudo] <xml file> <destination>\n";
+my ($xml_file_list, $DEST) = @ARGV;
+
+my $sudo = '';
+if ($>) {
+ $sudo = "sudo" if $want_sudo;
+ $ENV{PATH} = "/sbin:/usr/sbin:$ENV{PATH}";
+}
+
+#$verbose = 1;
+
+my $initial_dir = cwd();
+my $ARCH = arch() =~ /i.86/ ? 'i386' : arch();
+my $LIB = arch() =~ /x86_64/ ? "lib64" : "lib";
+
+my $base_cpio_options = '-pumd --quiet';
+
+my $problem;
+my $tree = XML::Parser->new(Style => 'Tree')->parsefile($xml_file_list);
+
+my $main_node = decompose($tree);
+
+$main_node->{tag} eq 'list' or die "bad file $xml_file_list (main tag should be <list>)\n";
+
+handle_nodes({}, $main_node);
+
+$problem and exit 1;
+
+install_needed_libraries();
+
+final_cleanup();
+
+sub error {
+ my ($err) = @_;
+ warn "FATAL: $err\n";
+ $problem = 1;
+}
+
+sub final_cleanup() {
+ #- cpio creates directory 700, that's not nice
+ system("find $DEST -type d -print0 | xargs -0 $sudo chmod 755");
+}
+
+sub handle_nodes {
+ my ($env, $e) = @_;
+ handle_node($env, decompose($_)) foreach @{$e->{l}};
+}
+sub handle_node {
+ my ($env, $node) = @_;
+
+ if (!$node->{tag} && $node->{text} !~ /\S/) {
+ } elsif (!$node->{tag}) {
+ install($env, $node->{text});
+ } elsif ($node->{tag} eq 'if') {
+ my $cond = valid_cond($node->{attr});
+ handle_nodes($env, $node) if $cond;
+ } elsif ($node->{tag} eq 'if-not') {
+ my $cond = valid_cond($node->{attr});
+ handle_nodes($env, $node) if !$cond;
+ } elsif (member($node->{tag}, 'from', 'to', 'mode', 'filter')) {
+ handle_nodes(add_to_env($env, $node->{tag} => $node->{attr}), $node);
+ } else {
+ warn "expecting tag <from>, not <$node->{tag}>\n";
+ }
+}
+
+sub valid_cond {
+ my ($attr) = @_;
+ every {
+ if ($_ eq 'ARCH') {
+ $ARCH =~ /$attr->{$_}/;
+ } elsif ($_ eq 'set') {
+ $ENV{$attr->{$_}};
+ } else {
+ die "<if>: unknown condition $_\n";
+ }
+ } keys %$attr;
+}
+
+sub add_to_env {
+ my ($env, $tag, $attr) = @_;
+ my %env = map_each { $::a => +{%$::b} } %$env;
+ foreach (keys %$attr) {
+ !$env{$tag}{$_} or die qq(overriding attribute <$tag $_="$env{$tag}{$_}"> with $_="$attr->{$_}"\n);
+ $env{$tag}{$_} = $attr->{$_};
+ }
+ \%env;
+}
+
+sub group_by_n {
+ my ($n, $l) = @_;
+ my (@r, $subl);
+ my $i = 0;
+ foreach (@$l) {
+ if ($i % $n == 0) {
+ push @r, $subl = [];
+ }
+ push @$subl, $_;
+ $i++;
+ }
+ @r;
+}
+
+sub identify_file {
+ my ($dev, $ino) = @_;
+ "$dev:$ino";
+}
+
+sub all_files_rec_ {
+ my ($d) = @_;
+
+ $d, -d $d && ! -l $d ? map { all_files_rec_("$d/$_") } all($d) : ();
+}
+
+sub expand_macros {
+ my ($f) = @_;
+ $f =~ s!\bLIB\b!$LIB!g;
+ $f =~ s!\bARCH\b!$ARCH!ge;
+ $f =~ s!\$\((\w+)\)!$ENV{$1} || die "$1 undefined\n"!ge;
+ $f;
+}
+
+my %needed_libraries;
+sub collect_needed_libraries {
+ my (@to_check) = @_;
+ while (@to_check) {
+ my $to_check = join(' ', @to_check);
+ my @l = `ldd $to_check 2>/dev/null` =~ m! => (/\S+)!g;
+ foreach (@l) {
+ if ($main_node->{attr}{'no-arch-libraries'}) {
+ #- replace /lib/tls or /lib/i686 with /lib
+ s!^(/lib(64)?/).*?/!$1! if arch() !~ /x86_64/;
+ }
+ }
+ @to_check = grep { !$needed_libraries{$_}++ } @l;
+ @to_check = ();
+ }
+}
+sub install_needed_libraries {
+ copy_files('', $DEST, [ keys %needed_libraries ], '', '--dereference');
+}
+
+sub collect_needed_perl_files {
+ my ($local_rep, $dest, @scripts) = @_;
+
+ my (%local, %global);
+ foreach my $script (@scripts) {
+ foreach (`strace -efile perl -cw -I$local_rep $script 2>&1`) {
+ my ($f) = /^open\("(.*?)",.*\)\s*=\s*\d+$/ or next;
+ if ($f =~ m!^\Q$local_rep\E/(.*)!) {
+ $local{$1} = 1;
+ } elsif (begins_with($f, '/dev/')) {
+ # skip
+ } elsif (begins_with($f, '/')) {
+ if ($main_node->{attr}{'no-arch-libraries'}) {
+ #- replace /lib/tls or /lib/i686 with /lib
+ $f =~ s!^(/lib(64)?/).*?/!$1! if arch() !~ /x86_64/;
+ }
+ $global{$f} = 1;
+ }
+ }
+ }
+ [ keys %local ], [ keys %global ];
+}
+
+sub copy_files {
+ my ($working_dir, $to_dir, $files, $b_flatten, @options) = @_;
+
+ if ($b_flatten) {
+ mkdir_p($to_dir);
+ my $options = join(' ', '-r', @options);
+ foreach (group_by_n(20, $files)) {
+ warn "cp $options to_dir $to_dir from $working_dir: @$_\n" if $verbose;
+ system("cd $working_dir ; $sudo cp $options @$_ $to_dir");
+ }
+ } else {
+ my $options = join(' ', $base_cpio_options, @options);
+ warn "cpio $options to_dir=$to_dir from=$working_dir: @$files\n" if $verbose;
+ open(my $F, "| cd $working_dir ; $sudo cpio $options $to_dir");
+ print $F "$_\n" foreach @$files;
+ close($F) or die "cpio $to_dir failed\n";
+ }
+}
+
+sub install {
+ my ($env, $text) = @_;
+
+ my $from_dir = expand_macros($env->{from}{dir});
+ my $to_dir = $DEST . expand_macros($env->{to}{dir} || $env->{to}{flatten} && $from_dir || '');
+ my $copy_mode = $env->{mode}{copy} || '';
+ my $working_dir = '.';
+
+ my $expand = $env->{from}{expand} || '';
+
+ my $disallow_from_dir = sub {
+ !$from_dir or die "from dir not allowed with $expand binary\n";
+ };
+
+ my $from_file = sub {
+ my ($rel, $b_full_glob, $b_recursive_dirs) = @_;
+ my $f = expand_macros($from_dir ? "$from_dir/$rel" : $rel);
+ my @l = $f;
+ chdir $working_dir;
+ if ($f =~ /\*/ || $b_full_glob) {
+ @l = File::Glob::bsd_glob($f); #- using bsd_glob because CORE::glob() splits on whitespace and we don't want this
+ if (@l == 0) {
+ error("no match for $f");
+ } elsif (@l == 1 || $b_full_glob) {
+ } else {
+ error("multiple match for $f");
+ @l = ();
+ }
+ } elsif (! -e $f) {
+ error("missing file $f ($rel) in $working_dir");
+ @l = ();
+ }
+ if (@l == 1 && -d $l[0] && $b_recursive_dirs) {
+ @l = all_files_rec_($l[0]);
+ }
+ @l = grep { !m!/(\.svn|CVS)($|/)! } @l;
+ if (my $re = $env->{from}{matching}) {
+ @l = grep { eval $re } @l;
+ }
+
+ collect_needed_libraries(grep { -f $_ && -x $_ } @l);
+
+ chdir $initial_dir;
+ @l;
+ };
+
+ my @text_l = $env->{from}{spaces_in_filename} ? $text =~ /^\s*(.*?)\s*$/ : split(' ', $text);
+ my @files;
+ if ($expand eq 'tar') {
+ foreach (@text_l) {
+ my ($tarball) = $from_file->($_) or next;
+ system('tar', 'xfj', $tarball, '-C', $to_dir);
+ }
+ # not filling @files, things are already done
+
+ } elsif ($expand eq 'command') {
+ @files = chomp_(`$text`);
+
+ } elsif ($expand eq 'glob') {
+ #- glob done in $from_file
+ @files = @text_l;
+
+ } elsif ($expand eq 'binary') {
+ $disallow_from_dir->();
+ my @PATH = qw(/sbin /bin /usr/bin /usr/sbin /usr/X11R6/bin);
+ foreach my $name (map { expand_macros($_) } @text_l) {
+ my @l = grep { -x $_ } map { "$_/$name" } @PATH;
+ @l or error("can't find binary $name"), next;
+ if (@l > 1) {
+ my @m = grep { ! -l $_ } @l;
+ if (@m == 1) {
+ my $id = identify_file($m[0]);
+ push @files, grep { -l $_ && identify_file($_) eq $id } @l;
+ }
+ @l = @m if @m;
+ }
+ if (@l > 1) {
+ warn "many matches for binary $name: " . join(' ', @l) . ", choosing $l[0]\n";
+ }
+ my $f = $l[0];
+ while (1) {
+ push @files, $f;
+ $copy_mode ne 'dereference' or last;
+ my $l = readlink($f) or last;
+ if ($l =~ m!/! && $l !~ m!^\.\..*/s?bin/[^/]+$!) {
+ warn "keeping symlink $f -> $l as is\n";
+ last;
+ }
+ $f = dirname($f) . '/' . $l;
+ }
+ }
+ $copy_mode ||= 'keep-links';
+ $env->{filter}{command} ||= 'strip';
+
+ } elsif ($expand eq 'rpm') {
+ $disallow_from_dir->();
+ foreach my $rpm (@text_l) {
+ my @l = chomp_(`rpm -ql $rpm`) or error("rpm $rpm must be installed");
+ push @files, @l;
+ }
+
+ } elsif ($expand eq 'perl') {
+ $disallow_from_dir->();
+ $from_dir = '/usr/lib/perl5/vendor_perl/*';
+ @files = @text_l;
+ } elsif ($expand eq 'main-perl') {
+ $disallow_from_dir->();
+ $from_dir = $Config{privlib};
+ @files = @text_l;
+ } elsif ($expand =~ /collect-perl-files/) {
+ my (undef, $local, $to) = split(' ', $expand);
+
+ @files = @text_l;
+ warn "collect-perl-files $local $to @files ($env->{filter}{command})\n";
+ my ($local_perl_files, $global_perl_files) = collect_needed_perl_files($local, $to, @files);
+ warn "collect-perl-files gave: ", join(' ', @$local_perl_files), "\n";
+# warn " and: ", join(' ', @$global_perl_files), "\n";
+ copy_and_filter($local =~ m!/! ? $local : "$working_dir/$local", "$DEST$to", $local_perl_files, $env->{filter}, '', '--dereference');
+ copy_and_filter('', $DEST, $global_perl_files, $env->{filter}, '', '--dereference');
+
+ } elsif ($expand) {
+ die "unknown expand method $expand\n";
+ } else {
+ @files = @text_l;
+
+ $env->{filter}{command} ||= 'strip' if $to_dir =~ m!/bin$!;
+ }
+
+ if ($env->{to}{dir} && $from_dir) {
+ $working_dir = $from_dir;
+ undef $from_dir;
+ }
+
+ my @all_files = map { $from_file->($_, $expand eq 'glob', $expand ne 'rpm') } @files;
+
+ my @options = (
+ if_($copy_mode ne 'keep-links', '--dereference'),
+ );
+ if (@all_files) {
+ copy_and_filter($working_dir, $to_dir, \@all_files, $env->{filter}, $env->{to}{flatten}, @options);
+ }
+}
+
+sub copy_and_filter {
+ my ($working_dir, $to_dir, $all_files, $filter, $flatten, @copy_options) = @_;
+
+ copy_files($working_dir, $to_dir, $all_files, $flatten, @copy_options);
+ apply_filter($to_dir, $filter, $all_files, $flatten);
+}
+
+sub apply_filter {
+ my ($to_dir, $filter, $all_files, $b_flatten) = @_;
+
+ chdir $to_dir;
+ foreach (group_by_n(20, $all_files)) {
+ my @l = $b_flatten ? (map { basename($_) } @$_) : (map { "./$_" } @$_);
+ @l = grep { ! -d $_ } @l or next;
+
+ if (my $subst = $filter->{subst}) {
+ system('perl', '-pi', '-e', $subst, @l);
+ }
+ if (my $command = $filter->{command}) {
+ $command = $initial_dir . "/$command" if $command =~ m!^..?/!;
+ if ($command =~ /simplify-drakx-modules/) {
+ @l = grep { !/\.so($|\.)/ } @l or next;
+ }
+ my @options = (
+ if_($command eq 'gzip', '-9f'),
+ if_($command eq 'strip', '2>/dev/null'),
+ );
+ warn "running $command @options @l\n" if $verbose;
+ system(join(' ', $command, @options, @l));
+ }
+ }
+ chdir $initial_dir;
+}
+
+sub decompose {
+ my ($tree) = @_;
+ my ($tag, $val) = @$tree;
+ if ($tag eq '0') {
+ { text => $val };
+ } else {
+ my ($attr, @l) = @$val;
+ { tag => $tag, attr => $attr, l => [ group_by2(@l) ] };
+ }
+}
diff --git a/tools/make_lang_png_transparent.c b/tools/make_lang_png_transparent.c
new file mode 100644
index 000000000..9a037e864
--- /dev/null
+++ b/tools/make_lang_png_transparent.c
@@ -0,0 +1,167 @@
+/*
+ * Guillaume Cottenceau (gc at mandriva.com)
+ *
+ * Copyright 2002-2005 Mandriva
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#define PNG_DEBUG 3
+#include <png.h>
+
+void abort_(const char * s, ...)
+{
+ va_list args;
+ va_start(args, s);
+ vfprintf(stderr, s, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ abort();
+}
+
+int x, y;
+
+int width, height;
+png_byte color_type;
+png_byte bit_depth;
+
+png_structp png_ptr;
+png_infop info_ptr;
+int number_of_passes;
+png_bytep * row_pointers;
+
+void read_png_file(char* file_name)
+{
+ char header[8]; // 8 is the maximum size that can be checked
+
+ /* open file and test for it being a png */
+ FILE *fp = fopen(file_name, "rb");
+ if (!fp)
+ abort_("[read_png_file] File %s could not be opened for reading", file_name);
+ fread(header, 1, 8, fp);
+ if (png_sig_cmp(header, 0, 8))
+ abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
+
+
+ /* initialize stuff */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (!png_ptr)
+ abort_("[read_png_file] png_create_read_struct failed");
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ abort_("[read_png_file] png_create_info_struct failed");
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[read_png_file] Error during init_io");
+
+ png_init_io(png_ptr, fp);
+ png_set_sig_bytes(png_ptr, 8);
+
+ png_read_info(png_ptr, info_ptr);
+
+ width = info_ptr->width;
+ height = info_ptr->height;
+ color_type = info_ptr->color_type;
+ bit_depth = info_ptr->bit_depth;
+
+ number_of_passes = png_set_interlace_handling(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
+
+
+ /* read file */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[read_png_file] Error during read_image");
+
+ row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
+ for (y=0; y<height; y++)
+ row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
+
+ png_read_image(png_ptr, row_pointers);
+}
+
+
+void write_png_file(char* file_name)
+{
+ /* create file */
+ FILE *fp = fopen(file_name, "wb");
+ if (!fp)
+ abort_("[write_png_file] File %s could not be opened for writing", file_name);
+
+
+ /* initialize stuff */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (!png_ptr)
+ abort_("[write_png_file] png_create_write_struct failed");
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ abort_("[write_png_file] png_create_info_struct failed");
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during init_io");
+
+ png_init_io(png_ptr, fp);
+
+
+ /* write header */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during writing header");
+
+ png_set_IHDR(png_ptr, info_ptr, width, height,
+ bit_depth, color_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_write_info(png_ptr, info_ptr);
+
+
+ /* write bytes */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during writing bytes");
+
+ png_write_image(png_ptr, row_pointers);
+
+
+ /* end write */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during end of write");
+
+ png_write_end(png_ptr, NULL);
+
+}
+
+void process_file(void)
+{
+ if (info_ptr->color_type != PNG_COLOR_TYPE_RGBA)
+ abort_("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (is %d)", info_ptr->color_type);
+
+ for (y=0; y<height; y++) {
+ png_byte* row = row_pointers[y];
+ for (x=0; x<width; x++) {
+ png_byte* ptr = &(row[x*4]);
+ ptr[3] = 255-ptr[0];
+ ptr[0] = ptr[1] = ptr[2] = 0;
+ }
+ }
+
+}
+
+
+int main(int argc, char **argv)
+{
+ if (argc != 3)
+ abort_("Usage: program_name <file_in> <file_out>");
+
+ read_png_file(argv[1]);
+ process_file();
+ write_png_file(argv[2]);
+}
diff --git a/tools/mdkinst_stage2_tool b/tools/mdkinst_stage2_tool
new file mode 100755
index 000000000..c1ef5d151
--- /dev/null
+++ b/tools/mdkinst_stage2_tool
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+error() {
+ cat <<EOF;
+usage: mdkinst_stage2_tool [--clean] [--compress | --uncompress] <stage2 dir> [<compressed file>]
+EOF
+ exit 1
+}
+
+if [ "$1" = "--clean" ]; then
+ CLEAN=1
+ shift
+fi
+
+[ $# = 2 -o $# = 3 ] || error
+
+if [ "$1" = "--compress" -o "$1" == "--uncompress" ]; then
+ ACTION=$1
+ shift
+ STAGE2_DIR="$1"
+ shift
+ LIVE_DIR="$STAGE2_DIR/live"
+ if [ -n "$1" ]; then
+ COMPRESSED_IMAGE=$1
+ shift
+ else
+ COMPRESSED_IMAGE="$STAGE2_DIR/mdkinst.sqfs"
+ fi
+else
+ error
+fi
+
+if [ $ACTION = "--compress" ]; then
+ which mksquashfs >/dev/null 2>/dev/null || { echo "missing command mksquashfs (from squashfs-tools)"; exit 1; }
+
+ [ -d "$LIVE_DIR" ] || error
+ echo "Creating $COMPRESSED_IMAGE from $LIVE_DIR"
+ rm -f $STAGE2_DIR/.room
+ mksquashfs $LIVE_DIR $COMPRESSED_IMAGE -all-root -noappend >/dev/null || { echo "mksquashfs failed"; exit 1; }
+ chmod 755 $COMPRESSED_IMAGE
+ echo foo > $STAGE2_DIR/.room
+ if [ -s $STAGE2_DIR/.room ]; then
+ rm -f $STAGE2_DIR/.room
+ [ -n "$CLEAN" ] && rm -rf $LIVE_DIR
+ else
+ echo "not enough space"
+ rm -f $COMPRESSED_IMAGE
+ exit 1
+ fi
+else
+ which unsquashfs >/dev/null 2>/dev/null || { echo "missing command unsquashfs (from squashfs-tools)"; exit 1; }
+
+ [ -f "$COMPRESSED_IMAGE" ] || error
+ echo "Creating $LIVE_DIR from $COMPRESSED_IMAGE"
+
+ if [ $EUID != "0" ]; then
+ SUDO="sudo"
+ PATH="/sbin:/usr/sbin:$PATH"
+ fi
+
+ unsquashfs -dest $LIVE_DIR $COMPRESSED_IMAGE || { rm -rf $LIVE_DIR; exit 1; }
+
+ [ -n "$CLEAN" ] && rm -f $COMPRESSED_IMAGE
+fi
+
+exit 0
diff --git a/tools/ntp_servers.pl b/tools/ntp_servers.pl
new file mode 100644
index 000000000..d0a4b6cc2
--- /dev/null
+++ b/tools/ntp_servers.pl
@@ -0,0 +1,303 @@
+#!/usr/bin/perl
+
+#open F, "/usr/bin/lynx -dump http://www.eecis.udel.edu/~mills/ntp/clock1a.html|";
+open(my $G, "/usr/bin/lynx -dump http://www.eecis.udel.edu/~mills/ntp/clock2a.html|");
+
+# Chris Kloiber <ckloiber@redhat.com> writes:
+# > It's not considered polite to use the Stratum 1 servers for purposes that
+# > are not absolutely critical. I would use Stratum 2 servers and live with
+# > the few nanoseconds difference.
+#parse() while <F>;
+
+parse($_) while <$G>;
+
+my @all;
+my ($l, $nb);
+sub parse {
+ local ($_) = @_;
+ /Active Servers/ .. /Discontinued Service/ or return;
+ if (/^\s+\d+\. ([A-Z ]*[A-Z]);?\s+([.\w-]+)/) {
+ push @all, $l = { name => $2, indic => $1 };
+ $nb = 0;
+ } else {
+ s/^\s*//;
+ s/\s*$//;
+ my ($field, $val) = /^(.*):\s*(.*)/;
+ if ($field =~ /policy/i) {
+ $field = "policy";
+ $val = lc join(' ', split(' ', $val));
+ $val =~ s/glad to receive a note//;
+ $val =~ s/(but )?please send (a )?message to notify//;
+ $val =~ s/an email note is appreciated//;
+ $val =~ s/please send a message with the//;
+ $val =~ s/no need to notify//;
+ $val =~ s/[(), .;]*$//;
+ $val = "open access" if $val eq "public";
+ warn "$val ($all[-1]{name})\n" if $val ne 'open access';
+ } elsif ($field =~ /^Contact|Synchroni[sz]ation|Location|Geographic\s+Coordinates|Service\s+Area|Note$/i) {
+ } else {
+# warn "bad line ($field) $_\n";
+ return;
+ }
+ $l->{$field} .= ($l->{$field} && ' ') . $val;
+ }
+ $nb++;
+}
+
+
+use Data::Dumper;
+#warn Dumper(\@all);
+
+foreach (grep { $_->{policy} eq 'open access' } @all) {
+ my ($country, $state) = split ' ', $_->{indic};
+ $country = ucfirst(lc $country_codes{$country});
+ $country .= " $state" if $state;
+ printf "\t'%s' => '%s',\n", lc($_->{name}), $country;
+}
+
+BEGIN {
+%country_codes = ( # from ftp://ftp.ripe.net/iso3166-countrycodes
+"AF", "AFGHANISTAN",
+"AL", "ALBANIA",
+"DZ", "ALGERIA",
+"AS", "AMERICAN SAMOA",
+"AD", "ANDORRA",
+"AO", "ANGOLA",
+"AI", "ANGUILLA",
+"AQ", "ANTARCTICA",
+"AG", "ANTIGUA AND BARBUDA",
+"AR", "ARGENTINA",
+"AM", "ARMENIA",
+"AW", "ARUBA",
+"AU", "AUSTRALIA",
+"AT", "AUSTRIA",
+"AZ", "AZERBAIJAN",
+"BS", "BAHAMAS",
+"BH", "BAHRAIN",
+"BD", "BANGLADESH",
+"BB", "BARBADOS",
+"BY", "BELARUS",
+"BE", "BELGIUM",
+"BZ", "BELIZE",
+"BJ", "BENIN",
+"BM", "BERMUDA",
+"BT", "BHUTAN",
+"BO", "BOLIVIA",
+"BA", "BOSNIA AND HERZEGOWINA",
+"BW", "BOTSWANA",
+"BV", "BOUVET ISLAND",
+"BR", "BRAZIL",
+"IO", "BRITISH INDIAN OCEAN TERRITORY",
+"BN", "BRUNEI DARUSSALAM",
+"BG", "BULGARIA",
+"BF", "BURKINA FASO",
+"BI", "BURUNDI",
+"KH", "CAMBODIA",
+"CM", "CAMEROON",
+"CA", "CANADA",
+"CV", "CAPE VERDE",
+"KY", "CAYMAN ISLANDS",
+"CF", "CENTRAL AFRICAN REPUBLIC",
+"TD", "CHAD",
+"CL", "CHILE",
+"CN", "CHINA",
+"CX", "CHRISTMAS ISLAND",
+"CC", "COCOS (KEELING) ISLANDS",
+"CO", "COLOMBIA",
+"KM", "COMOROS",
+"CG", "CONGO",
+"CD", "CONGO, THE DEMOCRATIC REPUBLIC OF THE",
+"CK", "COOK ISLANDS",
+"CR", "COSTA RICA",
+"CI", "COTE D'IVOIRE",
+"HR", "CROATIA",
+"CU", "CUBA",
+"CY", "CYPRUS",
+"CZ", "CZECH REPUBLIC",
+"DK", "DENMARK",
+"DJ", "DJIBOUTI",
+"DM", "DOMINICA",
+"DO", "DOMINICAN REPUBLIC",
+"TP", "EAST TIMOR",
+"EC", "ECUADOR",
+"EG", "EGYPT",
+"SV", "EL SALVADOR",
+"GQ", "EQUATORIAL GUINEA",
+"ER", "ERITREA",
+"EE", "ESTONIA",
+"ET", "ETHIOPIA",
+"FK", "FALKLAND ISLANDS (MALVINAS)",
+"FO", "FAROE ISLANDS",
+"FJ", "FIJI",
+"FI", "FINLAND",
+"FR", "FRANCE",
+"FX", "FRANCE, METROPOLITAN",
+"GF", "FRENCH GUIANA",
+"PF", "FRENCH POLYNESIA",
+"TF", "FRENCH SOUTHERN TERRITORIES",
+"GA", "GABON",
+"GM", "GAMBIA",
+"GE", "GEORGIA",
+"DE", "GERMANY",
+"GH", "GHANA",
+"GI", "GIBRALTAR",
+"GR", "GREECE",
+"GL", "GREENLAND",
+"GD", "GRENADA",
+"GP", "GUADELOUPE",
+"GU", "GUAM",
+"GT", "GUATEMALA",
+"GN", "GUINEA",
+"GW", "GUINEA-BISSAU",
+"GY", "GUYANA",
+"HT", "HAITI",
+"HM", "HEARD AND MC DONALD ISLANDS",
+"VA", "HOLY SEE (VATICAN CITY STATE)",
+"HN", "HONDURAS",
+"HK", "HONG KONG",
+"HU", "HUNGARY",
+"IS", "ICELAND",
+"IN", "INDIA",
+"ID", "INDONESIA",
+"IR", "IRAN (ISLAMIC REPUBLIC OF)",
+"IQ", "IRAQ",
+"IE", "IRELAND",
+"IL", "ISRAEL",
+"IT", "ITALY",
+"JM", "JAMAICA",
+"JP", "JAPAN",
+"JO", "JORDAN",
+"KZ", "KAZAKHSTAN",
+"KE", "KENYA",
+"KI", "KIRIBATI",
+"KP", "KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF",
+"KR", "KOREA, REPUBLIC OF",
+"KW", "KUWAIT",
+"KG", "KYRGYZSTAN",
+"LA", "LAO PEOPLE'S DEMOCRATIC REPUBLIC",
+"LV", "LATVIA",
+"LB", "LEBANON",
+"LS", "LESOTHO",
+"LR", "LIBERIA",
+"LY", "LIBYAN ARAB JAMAHIRIYA",
+"LI", "LIECHTENSTEIN",
+"LT", "LITHUANIA",
+"LU", "LUXEMBOURG",
+"MO", "MACAU",
+"MK", "MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF",
+"MG", "MADAGASCAR",
+"MW", "MALAWI",
+"MY", "MALAYSIA",
+"MV", "MALDIVES",
+"ML", "MALI",
+"MT", "MALTA",
+"MH", "MARSHALL ISLANDS",
+"MQ", "MARTINIQUE",
+"MR", "MAURITANIA",
+"MU", "MAURITIUS",
+"YT", "MAYOTTE",
+"MX", "MEXICO",
+"FM", "MICRONESIA, FEDERATED STATES OF",
+"MD", "MOLDOVA, REPUBLIC OF",
+"MC", "MONACO",
+"MN", "MONGOLIA",
+"MS", "MONTSERRAT",
+"MA", "MOROCCO",
+"MZ", "MOZAMBIQUE",
+"MM", "MYANMAR",
+"NA", "NAMIBIA",
+"NR", "NAURU",
+"NP", "NEPAL",
+"NL", "NETHERLANDS",
+"AN", "NETHERLANDS ANTILLES",
+"NC", "NEW CALEDONIA",
+"NZ", "NEW ZEALAND",
+"NI", "NICARAGUA",
+"NE", "NIGER",
+"NG", "NIGERIA",
+"NU", "NIUE",
+"NF", "NORFOLK ISLAND",
+"MP", "NORTHERN MARIANA ISLANDS",
+"NO", "NORWAY",
+"OM", "OMAN",
+"PK", "PAKISTAN",
+"PW", "PALAU",
+"PA", "PANAMA",
+"PG", "PAPUA NEW GUINEA",
+"PY", "PARAGUAY",
+"PE", "PERU",
+"PH", "PHILIPPINES",
+"PN", "PITCAIRN",
+"PL", "POLAND",
+"PT", "PORTUGAL",
+"PR", "PUERTO RICO",
+"QA", "QATAR",
+"RE", "REUNION",
+"RO", "ROMANIA",
+"RU", "RUSSIA",
+"RW", "RWANDA",
+"KN", "SAINT KITTS AND NEVIS",
+"LC", "SAINT LUCIA",
+"VC", "SAINT VINCENT AND THE GRENADINES",
+"WS", "SAMOA",
+"SM", "SAN MARINO",
+"ST", "SAO TOME AND PRINCIPE",
+"SA", "SAUDI ARABIA",
+"SN", "SENEGAL",
+"SC", "SEYCHELLES",
+"SL", "SIERRA LEONE",
+"SG", "SINGAPORE",
+"SK", "SLOVAKIA (Slovak Republic)",
+"SI", "SLOVENIA",
+"SB", "SOLOMON ISLANDS",
+"SO", "SOMALIA",
+"ZA", "SOUTH AFRICA",
+"GS", "SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS",
+"ES", "SPAIN",
+"LK", "SRI LANKA",
+"SH", "ST. HELENA",
+"PM", "ST. PIERRE AND MIQUELON",
+"SD", "SUDAN",
+"SR", "SURINAME",
+"SJ", "SVALBARD AND JAN MAYEN ISLANDS",
+"SZ", "SWAZILAND",
+"SE", "SWEDEN",
+"CH", "SWITZERLAND",
+"SY", "SYRIAN ARAB REPUBLIC",
+"TW", "TAIWAN, PROVINCE OF CHINA",
+"TJ", "TAJIKISTAN",
+"TZ", "TANZANIA, UNITED REPUBLIC OF",
+"TH", "THAILAND",
+"TG", "TOGO",
+"TK", "TOKELAU",
+"TO", "TONGA",
+"TT", "TRINIDAD AND TOBAGO",
+"TN", "TUNISIA",
+"TR", "TURKEY",
+"TM", "TURKMENISTAN",
+"TC", "TURKS AND CAICOS ISLANDS",
+"TV", "TUVALU",
+"UG", "UGANDA",
+"UA", "UKRAINE",
+"AE", "UNITED ARAB EMIRATES",
+"GB", "UNITED KINGDOM",
+"US", "UNITED STATES",
+"UM", "UNITED STATES MINOR OUTLYING ISLANDS",
+"UY", "URUGUAY",
+"UZ", "UZBEKISTAN",
+"VU", "VANUATU",
+"VE", "VENEZUELA",
+"VN", "VIET NAM",
+"VG", "VIRGIN ISLANDS (BRITISH)",
+"VI", "VIRGIN ISLANDS (U.S.)",
+"WF", "WALLIS AND FUTUNA ISLANDS",
+"EH", "WESTERN SAHARA",
+"YE", "YEMEN",
+"YU", "YUGOSLAVIA",
+"ZM", "ZAMBIA",
+"ZW", "ZIMBABWE",
+
+#added
+"UK", "UNITED KINGDOM",
+);
+}
diff --git a/tools/rpcinfo-flushed.c b/tools/rpcinfo-flushed.c
new file mode 100644
index 000000000..16303406d
--- /dev/null
+++ b/tools/rpcinfo-flushed.c
@@ -0,0 +1,740 @@
+#define _(x) x
+
+/* @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC */
+#if !defined(lint) && defined (SCCSID)
+static char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
+#endif
+
+/*
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * rpcinfo: ping a particular rpc program
+ * or dump the portmapper
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <signal.h>
+#include <ctype.h>
+#include <locale.h>
+#include <libintl.h>
+
+#define MAXHOSTLEN 256
+
+#define MIN_VERS ((u_long) 0)
+#define MAX_VERS ((u_long) 4294967295UL)
+
+static void udpping (u_short portflag, int argc, char **argv);
+static void tcpping (u_short portflag, int argc, char **argv);
+static int pstatus (CLIENT *client, u_long prognum, u_long vers);
+static void pmapdump (int argc, char **argv);
+static bool_t reply_proc (void *res, struct sockaddr_in *who);
+static void brdcst (int argc, char **argv) __attribute__ ((noreturn));
+static void deletereg (int argc, char **argv);
+static void usage (void);
+static u_long getprognum (char *arg);
+static u_long getvers (char *arg);
+static void get_inet_address (struct sockaddr_in *addr, char *host);
+
+/*
+ * Functions to be performed.
+ */
+#define NONE 0 /* no function */
+#define PMAPDUMP 1 /* dump portmapper registrations */
+#define TCPPING 2 /* ping TCP service */
+#define UDPPING 3 /* ping UDP service */
+#define BRDCST 4 /* ping broadcast UDP service */
+#define DELETES 5 /* delete registration for the service */
+
+int
+main (int argc, char **argv)
+{
+ register int c;
+ int errflg;
+ int function;
+ u_short portnum;
+
+ setlocale (LC_ALL, "");
+
+ function = NONE;
+ portnum = 0;
+ errflg = 0;
+ while ((c = getopt (argc, argv, "ptubdn:")) != -1)
+ {
+ switch (c)
+ {
+
+ case 'p':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = PMAPDUMP;
+ break;
+
+ case 't':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = TCPPING;
+ break;
+
+ case 'u':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = UDPPING;
+ break;
+
+ case 'b':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = BRDCST;
+ break;
+
+ case 'n':
+ portnum = (u_short) atoi (optarg); /* hope we don't get bogus # */
+ break;
+
+ case 'd':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = DELETES;
+ break;
+
+ case '?':
+ errflg = 1;
+ }
+ }
+
+ if (errflg || function == NONE)
+ {
+ usage ();
+ return 1;
+ }
+
+ switch (function)
+ {
+
+ case PMAPDUMP:
+ if (portnum != 0)
+ {
+ usage ();
+ return 1;
+ }
+ pmapdump (argc - optind, argv + optind);
+ break;
+
+ case UDPPING:
+ udpping (portnum, argc - optind, argv + optind);
+ break;
+
+ case TCPPING:
+ tcpping (portnum, argc - optind, argv + optind);
+ break;
+
+ case BRDCST:
+ if (portnum != 0)
+ {
+ usage ();
+ return 1;
+ }
+ brdcst (argc - optind, argv + optind);
+ break;
+
+ case DELETES:
+ deletereg (argc - optind, argv + optind);
+ break;
+ }
+
+ return 0;
+}
+
+static void
+udpping (portnum, argc, argv)
+ u_short portnum;
+ int argc;
+ char **argv;
+{
+ struct timeval to;
+ struct sockaddr_in addr;
+ enum clnt_stat rpc_stat;
+ CLIENT *client;
+ u_long prognum, vers, minvers, maxvers;
+ int sock = RPC_ANYSOCK;
+ struct rpc_err rpcerr;
+ int failure;
+
+ if (argc < 2 || argc > 3)
+ {
+ usage ();
+ exit (1);
+ }
+ prognum = getprognum (argv[1]);
+ get_inet_address (&addr, argv[0]);
+ /* Open the socket here so it will survive calls to clnt_destroy */
+ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ {
+ perror ("rpcinfo: socket");
+ exit (1);
+ }
+ failure = 0;
+ if (argc == 2)
+ {
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ addr.sin_port = htons (portnum);
+ to.tv_sec = 5;
+ to.tv_usec = 0;
+ if ((client = clntudp_create (&addr, prognum, (u_long) 0,
+ to, &sock)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu is not available\n"), prognum);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void,
+ (char *) NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ addr.sin_port = htons (portnum);
+ to.tv_sec = 5;
+ to.tv_usec = 0;
+ if ((client = clntudp_create (&addr, prognum, MAX_VERS,
+ to, &sock)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu version %lu is not available\n"),
+ prognum, MAX_VERS);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_void, NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ }
+ else
+ {
+ (void) pstatus (client, prognum, MAX_VERS);
+ exit (1);
+ }
+ }
+ else
+ {
+ (void) pstatus (client, prognum, (u_long) 0);
+ exit (1);
+ }
+ clnt_destroy (client);
+ for (vers = minvers; vers <= maxvers; vers++)
+ {
+ addr.sin_port = htons (portnum);
+ to.tv_sec = 5;
+ to.tv_usec = 0;
+ if ((client = clntudp_create (&addr, prognum, vers,
+ to, &sock)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu version %lu is not available\n"),
+ prognum, vers);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_void, NULL, to);
+ if (pstatus (client, prognum, vers) < 0)
+ failure = 1;
+ clnt_destroy (client);
+ }
+ }
+ else
+ {
+ vers = getvers (argv[2]);
+ addr.sin_port = htons (portnum);
+ to.tv_sec = 5;
+ to.tv_usec = 0;
+ if ((client = clntudp_create (&addr, prognum, vers,
+ to, &sock)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu version %lu is not available\n"),
+ prognum, vers);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL, to);
+ if (pstatus (client, prognum, vers) < 0)
+ failure = 1;
+ }
+ (void) close (sock); /* Close it up again */
+ if (failure)
+ exit (1);
+}
+
+static void
+tcpping (portnum, argc, argv)
+ u_short portnum;
+ int argc;
+ char **argv;
+{
+ struct timeval to;
+ struct sockaddr_in addr;
+ enum clnt_stat rpc_stat;
+ CLIENT *client;
+ u_long prognum, vers, minvers, maxvers;
+ int sock = RPC_ANYSOCK;
+ struct rpc_err rpcerr;
+ int failure;
+
+ if (argc < 2 || argc > 3)
+ {
+ usage ();
+ exit (1);
+ }
+ prognum = getprognum (argv[1]);
+ get_inet_address (&addr, argv[0]);
+ failure = 0;
+ if (argc == 2)
+ {
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ addr.sin_port = htons (portnum);
+ if ((client = clnttcp_create (&addr, prognum, MIN_VERS,
+ &sock, 0, 0)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu is not available\n"), prognum);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ addr.sin_port = htons (portnum);
+ if ((client = clnttcp_create (&addr, prognum, MAX_VERS,
+ &sock, 0, 0)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu version %lu is not available\n"),
+ prognum, MAX_VERS);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_void, NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ }
+ else
+ {
+ (void) pstatus (client, prognum, MAX_VERS);
+ exit (1);
+ }
+ }
+ else
+ {
+ (void) pstatus (client, prognum, MIN_VERS);
+ exit (1);
+ }
+ clnt_destroy (client);
+ (void) close (sock);
+ sock = RPC_ANYSOCK; /* Re-initialize it for later */
+ for (vers = minvers; vers <= maxvers; vers++)
+ {
+ addr.sin_port = htons (portnum);
+ if ((client = clnttcp_create (&addr, prognum, vers,
+ &sock, 0, 0)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu version %lu is not available\n"),
+ prognum, vers);
+ exit (1);
+ }
+ to.tv_usec = 0;
+ to.tv_sec = 10;
+ rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL, to);
+ if (pstatus (client, prognum, vers) < 0)
+ failure = 1;
+ clnt_destroy (client);
+ (void) close (sock);
+ sock = RPC_ANYSOCK;
+ }
+ }
+ else
+ {
+ vers = getvers (argv[2]);
+ addr.sin_port = htons (portnum);
+ if ((client = clnttcp_create (&addr, prognum, vers, &sock,
+ 0, 0)) == NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ printf (_("program %lu version %lu is not available\n"),
+ prognum, vers);
+ exit (1);
+ }
+ to.tv_usec = 0;
+ to.tv_sec = 10;
+ rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL, to);
+ if (pstatus (client, prognum, vers) < 0)
+ failure = 1;
+ }
+ if (failure)
+ exit (1);
+}
+
+/*
+ * This routine should take a pointer to an "rpc_err" structure, rather than
+ * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
+ * a CLIENT structure rather than a pointer to an "rpc_err" structure.
+ * As such, we have to keep the CLIENT structure around in order to print
+ * a good error message.
+ */
+static int
+pstatus (client, prognum, vers)
+ register CLIENT *client;
+ u_long prognum;
+ u_long vers;
+{
+ struct rpc_err rpcerr;
+
+ clnt_geterr (client, &rpcerr);
+ if (rpcerr.re_status != RPC_SUCCESS)
+ {
+ clnt_perror (client, "rpcinfo");
+ printf (_("program %lu version %lu is not available\n"), prognum, vers);
+ return -1;
+ }
+ else
+ {
+ printf (_("program %lu version %lu ready and waiting\n"), prognum, vers);
+ return 0;
+ }
+}
+
+static void
+pmapdump (argc, argv)
+ int argc;
+ char **argv;
+{
+ struct sockaddr_in server_addr;
+ register struct hostent *hp;
+ struct pmaplist *head = NULL;
+ int socket = RPC_ANYSOCK;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+
+ if (argc > 1)
+ {
+ usage ();
+ exit (1);
+ }
+ if (argc == 1)
+ get_inet_address (&server_addr, argv[0]);
+ else
+ {
+ bzero ((char *) &server_addr, sizeof server_addr);
+ server_addr.sin_family = AF_INET;
+ if ((hp = gethostbyname ("localhost")) != NULL)
+ bcopy (hp->h_addr, (caddr_t) & server_addr.sin_addr,
+ hp->h_length);
+ else
+ server_addr.sin_addr.s_addr = inet_addr ("0.0.0.0");
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ server_addr.sin_port = htons (PMAPPORT);
+ if ((client = clnttcp_create (&server_addr, PMAPPROG,
+ PMAPVERS, &socket, 50, 500)) == NULL)
+ {
+ clnt_pcreateerror (_("rpcinfo: can't contact portmapper"));
+ exit (1);
+ }
+ if (clnt_call (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_pmaplist, (caddr_t) &head,
+ minutetimeout) != RPC_SUCCESS)
+ {
+ fputs (_("rpcinfo: can't contact portmapper"), stderr);
+ fputs (": ", stderr);
+ clnt_perror (client, "rpcinfo");
+ exit (1);
+ }
+ if (head == NULL)
+ {
+ fputs (_("No remote programs registered.\n"), stdout);
+ }
+ else
+ {
+ fputs (_(" program vers proto port\n"), stdout);
+ for (; head != NULL; head = head->pml_next)
+ {
+ printf ("%10ld%5ld",
+ head->pml_map.pm_prog,
+ head->pml_map.pm_vers);
+ if (head->pml_map.pm_prot == IPPROTO_UDP)
+ printf ("%6s", "udp");
+ else if (head->pml_map.pm_prot == IPPROTO_TCP)
+ printf ("%6s", "tcp");
+ else
+ printf ("%6ld", head->pml_map.pm_prot);
+ printf ("%7ld", head->pml_map.pm_port);
+ rpc = getrpcbynumber (head->pml_map.pm_prog);
+ if (rpc)
+ printf (" %s\n", rpc->r_name);
+ else
+ printf ("\n");
+ }
+ }
+}
+
+/*
+ * reply_proc collects replies from the broadcast.
+ * to get a unique list of responses the output of rpcinfo should
+ * be piped through sort(1) and then uniq(1).
+ */
+
+/*ARGSUSED */
+static bool_t
+reply_proc (res, who)
+ void *res; /* Nothing comes back */
+ struct sockaddr_in *who; /* Who sent us the reply */
+{
+ register struct hostent *hp;
+
+ hp = gethostbyaddr ((char *) &who->sin_addr, sizeof who->sin_addr,
+ AF_INET);
+ printf ("%s %s\n", inet_ntoa (who->sin_addr),
+ (hp == NULL) ? _("(unknown)") : hp->h_name);
+ fflush(stdout);
+ return FALSE;
+}
+
+static void
+brdcst (argc, argv)
+ int argc;
+ char **argv;
+{
+ enum clnt_stat rpc_stat;
+ u_long prognum, vers;
+
+ if (argc != 2)
+ {
+ usage ();
+ exit (1);
+ }
+ prognum = getprognum (argv[0]);
+ vers = getvers (argv[1]);
+ rpc_stat = clnt_broadcast (prognum, vers, NULLPROC, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_void, NULL,
+ (resultproc_t) reply_proc);
+ if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
+ {
+ fprintf (stderr, _("rpcinfo: broadcast failed: %s\n"),
+ clnt_sperrno (rpc_stat));
+ exit (1);
+ }
+ exit (0);
+}
+
+static void
+deletereg (argc, argv)
+ int argc;
+ char **argv;
+{
+ u_long prog_num, version_num;
+
+ if (argc != 2)
+ {
+ usage ();
+ exit (1);
+ }
+ if (getuid ())
+ { /* This command allowed only to root */
+ fputs (_("Sorry. You are not root\n"), stderr);
+ exit (1);
+ }
+ prog_num = getprognum (argv[0]);
+ version_num = getvers (argv[1]);
+ if ((pmap_unset (prog_num, version_num)) == 0)
+ {
+ fprintf (stderr, _("rpcinfo: Could not delete registration for prog %s version %s\n"),
+ argv[0], argv[1]);
+ exit (1);
+ }
+}
+
+static void
+usage ()
+{
+ fputs (_("Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"),
+ stderr);
+ fputs (_(" rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"),
+ stderr);
+ fputs (_(" rpcinfo -p [ host ]\n"), stderr);
+ fputs (_(" rpcinfo -b prognum versnum\n"), stderr);
+ fputs (_(" rpcinfo -d prognum versnum\n"), stderr);
+}
+
+static u_long
+getprognum (arg)
+ char *arg;
+{
+ register struct rpcent *rpc;
+ register u_long prognum;
+
+ if (isalpha (*arg))
+ {
+ rpc = getrpcbyname (arg);
+ if (rpc == NULL)
+ {
+ fprintf (stderr, _("rpcinfo: %s is unknown service\n"), arg);
+ exit (1);
+ }
+ prognum = rpc->r_number;
+ }
+ else
+ {
+ prognum = (u_long) atoi (arg);
+ }
+
+ return prognum;
+}
+
+static u_long
+getvers (arg)
+ char *arg;
+{
+ register u_long vers;
+
+ vers = (int) atoi (arg);
+ return vers;
+}
+
+static void
+get_inet_address (addr, host)
+ struct sockaddr_in *addr;
+ char *host;
+{
+ register struct hostent *hp;
+
+ bzero ((char *) addr, sizeof *addr);
+ addr->sin_addr.s_addr = (u_long) inet_addr (host);
+ if (addr->sin_addr.s_addr == INADDR_NONE
+ || addr->sin_addr.s_addr == INADDR_ANY)
+ {
+ if ((hp = gethostbyname (host)) == NULL)
+ {
+ fprintf (stderr, _("rpcinfo: %s is unknown host\n"),
+ host);
+ exit (1);
+ }
+ bcopy (hp->h_addr, (char *) &addr->sin_addr, hp->h_length);
+ }
+ addr->sin_family = AF_INET;
+}
diff --git a/tools/serial_probe/Makefile b/tools/serial_probe/Makefile
new file mode 100644
index 000000000..86deb49f9
--- /dev/null
+++ b/tools/serial_probe/Makefile
@@ -0,0 +1,13 @@
+CFLAGS = -Wall -Os
+CFILES = $(wildcard *.c)
+OFILES = $(CFILES:%.c=%.o)
+GOAL = serial_probe
+
+$(GOAL): $(OFILES)
+
+serial.o: serial.c serial.h device.h kudzu.h
+serial_probe.o: serial_probe.c serial.h device.h
+serial_probe: serial_probe.o
+
+clean:
+ rm -f $(GOAL) $(OFILES) *~
diff --git a/tools/serial_probe/device.h b/tools/serial_probe/device.h
new file mode 100644
index 000000000..58d1414a0
--- /dev/null
+++ b/tools/serial_probe/device.h
@@ -0,0 +1,104 @@
+/* Copyright 1999-2003 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef _KUDZU_DEVICES_H_
+#define _KUDZU_DEVICES_H_
+
+#include <stdio.h>
+
+enum deviceClass {
+ /* device classes... this is somewhat ad-hoc */
+ CLASS_UNSPEC = ~0,
+ CLASS_OTHER = (1 << 0),
+ CLASS_NETWORK = (1 << 1),
+ CLASS_SCSI = (1 << 2),
+ CLASS_MOUSE = (1 << 3),
+ CLASS_AUDIO = (1 << 4),
+ CLASS_CDROM = (1 << 5),
+ CLASS_MODEM = (1 << 6),
+ CLASS_VIDEO = (1 << 7),
+ CLASS_TAPE = (1 << 8),
+ CLASS_FLOPPY = (1 << 9),
+ CLASS_SCANNER = (1 << 10),
+ CLASS_HD = (1 << 11),
+ CLASS_RAID = (1 << 12),
+ CLASS_PRINTER = (1 << 13),
+ CLASS_CAPTURE = (1 << 14),
+ CLASS_KEYBOARD = (1 << 15),
+ CLASS_MONITOR = (1 << 16),
+ CLASS_USB = (1 << 17),
+ CLASS_SOCKET = (1 << 18),
+ CLASS_FIREWIRE = (1 << 19),
+ CLASS_IDE = (1 << 20)
+};
+
+/* Update this if needed */
+#define CLASS_LAST CLASS_IDE
+
+enum deviceBus {
+ /* 'bus' that a device is attached to... this is also ad-hoc */
+ /* BUS_SBUS is sort of a misnomer - it's more or less Sun */
+ /* OpenPROM probing of all various associated non-PCI buses */
+ BUS_UNSPEC = ~0,
+ BUS_OTHER = (1 << 0),
+ BUS_PCI = (1 << 1),
+ BUS_SBUS = (1 << 2),
+ BUS_SERIAL = (1 << 3),
+ BUS_PSAUX = (1 << 4),
+ BUS_PARALLEL = (1 << 5),
+ BUS_SCSI = (1 << 6),
+ BUS_IDE = (1 << 7),
+ /* Again, misnomer */
+ BUS_KEYBOARD = (1 << 8),
+ BUS_DDC = (1 << 9),
+ BUS_USB = (1 << 10),
+ BUS_ISAPNP = (1 << 11),
+ BUS_MISC = (1 << 12),
+ BUS_FIREWIRE = (1 << 13),
+ BUS_PCMCIA = (1 << 14),
+ BUS_ADB = (1 << 15),
+ BUS_MACIO = (1 << 16)
+};
+
+struct device {
+ /* This pointer is used to make lists by the library. */
+ /* Do not expect it to remain constant (or useful) across library calls. */
+ struct device *next;
+ /* Used for ordering, and for aliasing (modem0, modem1, etc.) */
+ int index;
+ enum deviceClass type; /* type */
+ enum deviceBus bus; /* bus it's attached to */
+ char * device; /* device file associated with it */
+ char * driver; /* driver to load, if any */
+ char * desc; /* a description */
+ int detached; /* should we care if it disappears? */
+ struct device *(*newDevice) (struct device *old, struct device *new);
+ void (*freeDevice) (struct device *dev);
+ void (*writeDevice) (FILE *file, struct device *dev);
+ int (*compareDevice) (struct device *dev1, struct device *dev2);
+};
+
+struct device *newDevice(struct device *old, struct device *new);
+void freeDevice(struct device *dev);
+void writeDevice(FILE *file, struct device *dev);
+int compareDevice(struct device *dev1, struct device *dev2);
+struct device *readDevice(FILE *file);
+
+/* Most of these aren't implemented yet...... */
+/* Return everything found, even non-useful stuff */
+#define PROBE_ALL 1
+/* Don't do 'dangerous' probes that could do weird things (isapnp, serial) */
+#define PROBE_SAFE (1<<1)
+/* Stop at first device found */
+#define PROBE_ONE (1<<2)
+
+#endif
diff --git a/tools/serial_probe/kudzu.h b/tools/serial_probe/kudzu.h
new file mode 100644
index 000000000..f96565cca
--- /dev/null
+++ b/tools/serial_probe/kudzu.h
@@ -0,0 +1,26 @@
+/* Copyright 1999-2003 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _KUDZU_H_
+#define _KUDZU_H_
+
+/* kudzu: it grows on you */
+
+/* level of debugging output */
+#undef DEBUG_LEVEL
+
+#ifdef DEBUG_LEVEL
+#define DEBUG(s...) fprintf(stderr,s)
+#else
+#define DEBUG(s...) ;
+#endif
+
+#endif
diff --git a/tools/serial_probe/serial.c b/tools/serial_probe/serial.c
new file mode 100644
index 000000000..c84cbcff5
--- /dev/null
+++ b/tools/serial_probe/serial.c
@@ -0,0 +1,1136 @@
+/* Copyright 1999-2003 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * probe serial port for PnP/Legacy devices
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <libgen.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
+
+#include <asm/types.h>
+#include <linux/serial.h>
+
+#include "serial.h"
+#include "kudzu.h"
+
+/* character strings ARE null-terminated in the following structure */
+/* these elements are marked with a (string) in the comment */
+/* If PnP device sent 6 bit data stream, we've xlated by a 0x20 offset */
+/* When computing checksum, must remove this offset */
+struct pnp_com_id {
+ unsigned char xlate_6bit; /* does this contain xlated data */
+ unsigned char other_id[17]; /* backward compatibility with pre-PNP */
+ unsigned char other_len; /* length of the other_id */
+ unsigned char pnp_rev[2]; /* PnP revision bytes */
+ unsigned char pnp_rev_str[8]; /* PnP revision (string version) */
+ unsigned char eisa_id[4]; /* EISA Mfr identifier (string) */
+ unsigned char product_id[5]; /* Mfr determined product ID (string) */
+ unsigned char serial_number[9];/* Optional dev serial number (string) */
+ unsigned char class_name[33]; /* Optional PnP Class name (string) */
+ unsigned char driver_id[42]; /* Optional compat device IDs (string) */
+ unsigned char user_name[42]; /* Optional verbose product descr (string)*/
+ unsigned char checksum[2]; /* Optional checksum */
+};
+
+/* there are two possible bytes to signify the start of a PnP ID string */
+#define BeginPnP1 0x28
+#define BeginPnP2 0x08
+
+/* Likewise, two possible stop bytes */
+#define EndPnP1 0x29
+#define EndPnP2 0x09
+
+/* these chars indicate extensions to the base dev id exist */
+#define ExtendPnP1 0x5c
+#define ExtendPnP2 0x3c
+
+#define PNP_COM_MAXLEN 256
+
+/* results from initiating hardware probe of a hardware device */
+#define PNP_COM_FATAL 1 /* system error, check errno */
+#define PNP_COM_FAIL 2 /* probe ok, but found nothing */
+#define PNP_COM_OK 3 /* probe ok, we found it */
+
+/* types of devices we might find */
+/* if PNP_COM_PNPDEV is NOT set, its a legacy device */
+#define PNP_COM_MOUSE 1 /* its a mouse */
+#define PNP_COM_MODEM 2 /* its a modem */
+#define PNP_COM_OTHER 4 /* device is there, cant tell what kind */
+#define PNP_COM_NOEXIST 8 /* no device seen */
+#define PNP_COM_PNPDEV 512 /* its a PNP device */
+
+static void serialFreeDevice(struct serialDevice *dev) {
+ if (dev->pnpmfr) free(dev->pnpmfr);
+ if (dev->pnpmodel) free(dev->pnpmodel);
+ if (dev->pnpcompat) free(dev->pnpcompat);
+ if (dev->pnpdesc) free(dev->pnpdesc);
+ freeDevice((struct device *)dev);
+}
+
+static void serialWriteDevice(FILE *file, struct serialDevice *dev)
+{
+ writeDevice(file, (struct device *) dev);
+ if (dev->pnpmfr)
+ fprintf(file,"pnpmfr: %s\n",dev->pnpmfr);
+ if (dev->pnpmodel)
+ fprintf(file,"pnpmodel: %s\n",dev->pnpmodel);
+ if (dev->pnpcompat)
+ fprintf(file,"pnpcompat: %s\n",dev->pnpcompat);
+ if (dev->pnpdesc)
+ fprintf(file,"pnpdesc: %s\n",dev->pnpdesc);
+}
+
+static int serialCompareDevice( struct serialDevice *dev1, struct serialDevice *dev2)
+{
+ int x;
+
+ x = compareDevice((struct device *)dev1, (struct device *)dev2);
+ if (x && x!=2) return x;
+ if (dev1->pnpmfr && dev2->pnpmfr && strcmp(dev1->pnpmfr,dev2->pnpmfr))
+ return 1;
+ if ((!dev1->pnpmfr || !dev2->pnpmfr) && (dev1->pnpmfr != dev2->pnpmfr))
+ return 1;
+ if (dev1->pnpmodel && dev2->pnpmodel && strcmp(dev1->pnpmodel,dev2->pnpmodel))
+ return 1;
+ if ((!dev1->pnpmodel || !dev2->pnpmodel) && (dev1->pnpmodel != dev2->pnpmodel))
+ return 1;
+ if (dev1->pnpcompat && dev2->pnpcompat && strcmp(dev1->pnpcompat,dev2->pnpcompat))
+ return 1;
+ if ((!dev1->pnpcompat || !dev2->pnpcompat) && (dev1->pnpcompat != dev2->pnpcompat))
+ return 1;
+ if (dev1->pnpdesc && dev2->pnpdesc && strcmp(dev1->pnpdesc,dev2->pnpdesc))
+ return 1;
+ if ((!dev1->pnpdesc || !dev2->pnpdesc) && (dev1->pnpdesc != dev2->pnpdesc))
+ return 1;
+ return x;
+}
+
+
+struct serialDevice * serialNewDevice(struct serialDevice *dev) {
+ struct serialDevice *ret;
+
+ ret = malloc(sizeof(struct serialDevice));
+ memset(ret,'\0',sizeof(struct serialDevice));
+ ret=(struct serialDevice *)newDevice((struct device *)dev,(struct device *)ret);
+ ret->bus = BUS_SERIAL;
+ ret->newDevice = serialNewDevice;
+ ret->freeDevice = serialFreeDevice;
+ ret->writeDevice = serialWriteDevice;
+ ret->compareDevice = serialCompareDevice;
+ if (dev && dev->bus == BUS_SERIAL) {
+ if (dev->pnpmfr)
+ ret->pnpmfr=strdup(dev->pnpmfr);
+ if (dev->pnpmodel)
+ ret->pnpmodel=strdup(dev->pnpmodel);
+ if (dev->pnpcompat)
+ ret->pnpcompat=strdup(dev->pnpcompat);
+ if (dev->pnpdesc)
+ ret->pnpdesc=strdup(dev->pnpdesc);
+ }
+ return ret;
+}
+
+/*
+ * wait_input - wait until there is data available on fd,
+ * for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+
+static int wait_for_input (int fd, struct timeval *timo) {
+ fd_set ready;
+ int n;
+
+ FD_ZERO(&ready);
+ FD_SET(fd, &ready);
+
+ n = select(fd+1, &ready, NULL, &ready, timo);
+ return n;
+}
+
+static int open_serial_port( char *port ) {
+ int fd;
+
+ DEBUG("opening serial port %s...", port);
+
+ fd = open( port, O_RDWR | O_NONBLOCK);
+ if (fd < 0) {
+ DEBUG("failed.\n");
+ return -1;
+ } else {
+ DEBUG("successful.\n");
+ }
+
+ /* reset file so it is no longer in non-blocking mode */
+ if (fcntl(fd, F_SETFL, 0) < 0) {
+ close(fd);
+ DEBUG("Failed to set port to non-blocking mode\n");
+ return -1;
+ }
+
+ return fd;
+}
+
+/* <0 means ioctl error occurred */
+static int get_serial_lines( int fd ) {
+ int modem_lines;
+
+ ioctl(fd, TIOCMGET, &modem_lines);
+ return modem_lines;
+}
+
+/* <0 means ioctl error occurred */
+static int set_serial_lines( int fd, int modem_lines ) {
+ return ioctl(fd, TIOCMSET, &modem_lines);
+}
+
+/* set serial port to 1200 baud, 'nbits' bits, 1 stop, no parity */
+static int setup_serial_port( int fd, int nbits, struct termios *attr ) {
+
+ DEBUG("setting up serial port\n");
+
+ attr->c_iflag = IGNBRK | IGNPAR;
+ attr->c_cflag = 0;
+ attr->c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | PARENB);
+ attr->c_cflag |= CREAD | CLOCAL; /*| CRTSCTS ; */
+ if (nbits == 7)
+ attr->c_cflag |= CS7 | CSTOPB;
+ else
+ attr->c_cflag |= CS8;
+ attr->c_oflag = 0;
+ attr->c_lflag = 0;
+
+ attr->c_cc[VMIN] = 1;
+ attr->c_cc[VTIME] = 5;
+
+ if (cfsetospeed( attr, B1200))
+ return -1;
+ if (cfsetispeed( attr, B1200))
+ return -1;
+ return tcsetattr(fd, TCSANOW, attr);
+}
+
+/* Initialize the serial port to a known state *before* probing. This is
+ * apparently required for some Logitech mice, who will stubbornly refuse
+ * to respond to PnP probes after they've been opened by gpm or XFree.
+ */
+
+static int init_port(int fd) {
+ struct termios attr;
+
+ if (tcgetattr(fd,&attr))
+ return 1;
+
+ cfsetospeed(&attr, B2400);
+ cfsetispeed(&attr, B2400);
+ attr.c_iflag = IXON | ICRNL;
+ attr.c_cflag = CLOCAL | HUPCL | CREAD | B9600 | CS8;
+ attr.c_oflag = 0;
+ attr.c_lflag = 0;
+ return tcsetattr(fd, TCSANOW, &attr);
+}
+
+
+/* Request for PnP info from serial device */
+/* See page 6 of the pnpcom doc from Microsoft */
+/* Return code tells us what happened */
+/* */
+/* PNP_COM_FATAL - error, errno has reason */
+/* PNP_COM_OK - probe initiated successfully */
+static int init_pnp_com_seq1( int fd ) {
+ int modem_lines;
+ int temp;
+ int dsr_status;
+ int rc = PNP_COM_OK;
+ struct termios portattr;
+
+ DEBUG("initializing 1st PNP sequence\n");
+ if (init_port(fd))
+ return PNP_COM_FATAL;
+
+ modem_lines = get_serial_lines(fd);
+
+ /* COM port initialization, check for device enumerate */
+
+ /* turn on DTR, turn off RTS */
+ modem_lines |= TIOCM_DTR;
+ modem_lines &= ~TIOCM_RTS;
+ set_serial_lines(fd, modem_lines);
+
+ /* wait 200ms for DSR=1 */
+ usleep(200000);
+
+ dsr_status = get_serial_lines(fd) & TIOCM_DSR;
+ /* see if we got DSR coming up */
+
+ if (!dsr_status) {
+ DEBUG("Device did not set DSR\n");
+ }
+
+ /* COM port Setup, 1st phase */
+ temp = tcgetattr(fd, &portattr);
+ if (temp < 0)
+ return PNP_COM_FATAL;
+
+ /* now we set port to be 1200 baud, 7 bits, no parity, 1 stop bit */
+ temp = setup_serial_port( fd, 7, &portattr );
+ if (temp < 0)
+ return PNP_COM_FATAL;
+
+ /* we drop DTR and RTS */
+ modem_lines &= ~( TIOCM_RTS | TIOCM_DTR);
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* bring DTR back up */
+ modem_lines |= TIOCM_DTR;
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* Wait for response, 1st phase */
+ modem_lines |= TIOCM_RTS;
+ set_serial_lines(fd, modem_lines);
+ /* usleep(200000); => AQ: not valid as we should look to receive data during this time!! */
+
+ return rc;
+}
+
+
+/* Request for PnP info from serial device */
+/* See page 6 of the pnpcom doc from Microsoft */
+/* Always returns PNP_COM_OK */
+static int init_pnp_com_seq2( int fd ) {
+ int modem_lines;
+ int rc = PNP_COM_OK;
+
+ DEBUG("initializing 2nd PNP sequence\n");
+
+ modem_lines = get_serial_lines(fd);
+
+ /* COM port setup, 2nd phase */
+ /* turn off DTR and RTS */
+ modem_lines &= ~(TIOCM_DTR | TIOCM_RTS);
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* wait for response, 2nd phase */
+ /* turn on DTR and RTS */
+ modem_lines |= (TIOCM_DTR | TIOCM_RTS);
+ set_serial_lines(fd, modem_lines);
+ /* usleep(200000); => AQ: not valid as we should look to receive data during this time!! */
+
+ return rc;
+}
+
+
+/* Request for PnP info from serial modem device */
+/* Uses ATI9 code, may not do anything but return 'ERROR' */
+/* Return code tells us what happened */
+/* */
+/* PNP_COM_FATAL - error, errno has reason */
+/* PNP_COM_OK - probe initiated successfully */
+/* PNP_COM_FAIL - DSR never came on - try alterntives */
+/* means (ATI9?) to get PnP string */
+static int init_pnp_com_ati9( int fd ) {
+ int modem_lines;
+ int temp;
+ int done;
+ int respindex;
+ int starttime;
+ unsigned char resp[100], buf[2];
+ struct timeval timo;
+ struct termios portattr;
+
+ DEBUG("Querying ATI9 info from modem\n");
+ modem_lines = get_serial_lines(fd);
+
+ /* turn off RTS */
+ modem_lines &= ~TIOCM_RTS;
+ set_serial_lines(fd, modem_lines);
+
+ /* wait 200ms for DSR=1 */
+ usleep(200000);
+
+ /* now we set port to be 1200 baud, 8 bits, no parity, 1 stop bit */
+ temp = tcgetattr(fd, &portattr);
+ if (temp < 0) {
+ modem_lines |= TIOCM_DTR | TIOCM_RTS;
+ set_serial_lines(fd, modem_lines);
+ return PNP_COM_FATAL;
+ }
+
+ /* goto 1200 baud, 8 bits */
+ temp = setup_serial_port( fd, 8, &portattr );
+ if (temp < 0) {
+ modem_lines |= TIOCM_DTR | TIOCM_RTS;
+ set_serial_lines(fd, modem_lines);
+ return PNP_COM_FATAL;
+ }
+
+ /* turn on DTR and RTS */
+ modem_lines = get_serial_lines(fd);
+ modem_lines |= TIOCM_RTS | TIOCM_DTR;
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* send the 'AT' command */
+ DEBUG("Sending ATI9 command to modem\n");
+
+ write(fd, "ATI9\r", 5);
+
+ /* start reading - read the AT command back */
+ done = 0;
+ respindex= 0;
+ starttime=time(NULL);
+ memset(resp, 0, sizeof(resp));
+ while (!done) {
+ timo.tv_sec=0;
+ timo.tv_usec=250000;
+ if (wait_for_input(fd, &timo) > 0) {
+ temp = read( fd, buf, 1 );
+ if (temp < 0) {
+ if (errno != EAGAIN)
+ return PNP_COM_FATAL;
+ } else {
+ resp[respindex++] = buf[0];
+ resp[respindex] = 0;
+ }
+ } else
+ done = 1;
+
+ /* shouldnt run more than 5 seconds */
+ if (time(NULL)-starttime > 5 )
+ done = 1;
+
+ if (respindex > 6)
+ done = 1;
+
+ if (strstr(resp, "ATI9\r"))
+ done = 1;
+
+ DEBUG("ATI9 probe ->%d \"%s\"\n",respindex, resp);
+ }
+
+ /* see if we saw the 'OK' response */
+ if (strstr(resp, "("))
+ return PNP_COM_OK;
+ else
+ return PNP_COM_FAIL;
+
+ return PNP_COM_OK;
+}
+
+/* See if this is a legacy mouse device */
+/* Only called if the PnP probe above failed */
+/* We turn off the mouse via RS232 lines, then turn it on */
+/* If it spits out an 'M' character (at 1200 baud, 7N1) */
+/* it could be a mouse. */
+/* */
+/* Return code tells us what happened */
+/* */
+/* PNP_COM_FATAL - error, errno has reason */
+/* PNP_COM_OK - probe saw 'M' */
+/* PNP_COM_FAIL - Never saw the 'M' response */
+
+static int find_legacy_mouse( int fd ) {
+ int modem_lines;
+ int temp;
+ int done;
+ int starttime;
+ unsigned char resp[2];
+ struct timeval timo;
+ struct termios portattr;
+
+ DEBUG("looking for a legacy mouse\n");
+
+ /* now we set port to be 1200 baud, 7 bits, no parity, 1 stop bit */
+ temp = tcgetattr(fd, &portattr);
+ if (temp < 0)
+ return PNP_COM_FATAL;
+
+ /* goto 1200 baud, etc etc*/
+ temp = setup_serial_port( fd, 7, &portattr );
+ if (temp < 0)
+ return PNP_COM_FATAL;
+
+ /* we drop DTR and RTS */
+ modem_lines = get_serial_lines(fd);
+ modem_lines &= ~( TIOCM_RTS | TIOCM_DTR);
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* bring them DTR back up */
+ modem_lines |= TIOCM_DTR | TIOCM_RTS;
+ set_serial_lines(fd, modem_lines);
+
+ /* start reading - after first character we quit */
+ done = 0;
+ starttime=time(NULL);
+ while (!done) {
+ timo.tv_sec=0;
+ timo.tv_usec=250000;
+ if (wait_for_input(fd, &timo) > 0) {
+ temp = read( fd, resp, 1 );
+ if (temp < 0) {
+ if (errno != EAGAIN)
+ return PNP_COM_FATAL;
+ } else {
+ done = 1;
+ }
+ } else
+ done = 1;
+
+
+ /* shouldnt run more than 2 seconds */
+ if (time(NULL)-starttime > 2 )
+ done = 1;
+ }
+ if (*resp == 'M') {
+ DEBUG("Found legacy mouse\n");
+ return PNP_COM_OK;
+ } else
+ return PNP_COM_FAIL;
+}
+
+/* See if this is a legacy modem device */
+/* Only called if the PnP probe above failed */
+/* We send a '!AT' and see if we get an 'OK' back */
+/* */
+/* Return code tells us what happened */
+/* */
+/* PNP_COM_FATAL - error, errno has reason */
+/* PNP_COM_OK - probe saw 'OK' */
+/* PNP_COM_FAIL - Never saw the 'OK' response */
+static int find_legacy_modem( int fd ) {
+ int modem_lines;
+ int temp;
+ int done;
+ int respindex;
+ int starttime;
+ unsigned char resp[10], buf[2];
+ struct timeval timo;
+ struct termios portattr;
+
+ DEBUG("looking for a legacy modem\n");
+
+ /* now we set port to be 1200 baud, 8 bits, no parity, 1 stop bit */
+ temp = tcgetattr(fd, &portattr);
+ if (temp < 0)
+ return PNP_COM_FATAL;
+
+ /* goto 1200 baud, 8 bits */
+ temp = setup_serial_port( fd, 8, &portattr );
+ if (temp < 0)
+ return PNP_COM_FATAL;
+
+ /* turn on DTR and RTS */
+ modem_lines = get_serial_lines(fd);
+ modem_lines |= TIOCM_RTS | TIOCM_DTR;
+ set_serial_lines(fd, modem_lines);
+ usleep(200000);
+
+ /* send the 'AT' command */
+ DEBUG("Sending AT command to modem\n");
+
+ write(fd, "AT\r", 3);
+
+ /* start reading - we'll get AT command back first, then modem response */
+ done = 0;
+ respindex= 0;
+ starttime=time(NULL);
+ memset(resp, 0, sizeof(resp));
+ while (!done) {
+ timo.tv_sec=0;
+ timo.tv_usec=250000;
+ if (wait_for_input(fd, &timo) > 0) {
+ temp = read( fd, buf, 1 );
+ if (temp < 0) {
+ if (errno != EAGAIN)
+ return PNP_COM_FATAL;
+ } else {
+ resp[respindex++] = buf[0];
+ }
+ } else
+ done = 1;
+
+ /* shouldnt run more than 5 seconds */
+ if (time(NULL)-starttime > 5 )
+ done = 1;
+
+ if (respindex > 9)
+ done = 1;
+ }
+
+ /* see if we saw the 'OK' response */
+ if (strstr(resp, "OK"))
+ return PNP_COM_OK;
+ else
+ return PNP_COM_FAIL;
+}
+
+/* retrieve the PnP ID string */
+/* timeout after 3 seconds */
+/* should probably set a 200 msec timeout per char, as spec says */
+/* if no char received, we're done */
+static int read_pnp_string( int fd, unsigned char *pnp_string, int *pnp_len, int pnp_stringbuf_size ) {
+ int pnp_index;
+ int temp, done, counter;
+ int seen_start;
+ time_t starttime;
+ struct timeval timo;
+ unsigned char buf[80];
+ unsigned char end_char;
+
+ DEBUG("Attempting to read PNP ID string\n");
+
+ /* see if we have any input waiting */
+ pnp_index = 0;
+ seen_start = 0;
+ done = 0;
+ end_char = 0;
+ starttime=time(NULL);
+ while (!done) {
+ timo.tv_sec=0;
+ timo.tv_usec=250000;
+ if (wait_for_input(fd, &timo) > 0) {
+ temp = read( fd, buf, 1 );
+ if (temp < 0) {
+ if (errno != EAGAIN)
+ return PNP_COM_FAIL;
+ } else {
+ for (counter=0; counter < temp; counter++) {
+ pnp_string[pnp_index++] = buf[counter];
+ if (seen_start) {
+ if (buf[counter] == end_char) {
+ done=1;
+ break;
+ }
+ } else {
+ if (buf[counter] == BeginPnP1) {
+ seen_start = 1;
+ end_char = EndPnP1;
+ } else if (buf[counter] == BeginPnP2) {
+ seen_start = 1;
+ end_char = EndPnP2;
+ }
+ }
+ }
+ }
+ } else
+ done = 1;
+
+ /* shouldnt run more than 3 seconds */
+ if (time(NULL)-starttime > 3 )
+ done = 1;
+
+ if (pnp_index >= pnp_stringbuf_size)
+ done = 1;
+ }
+ pnp_string[pnp_index] = 0;
+ *pnp_len=pnp_index;
+ if(*pnp_len > 0)
+ return PNP_COM_OK;
+ else /* allows to call seq2 to be conformant */
+ return PNP_COM_FAIL;
+}
+
+/* parse the PnP ID string into components */
+static int parse_pnp_string( unsigned char *pnp_id_string, int pnp_len,
+ struct pnp_com_id *pnp_id ) {
+ unsigned char *p1, *p2;
+ unsigned char *start;
+ unsigned char *end;
+ unsigned char *curpos;
+ unsigned char *endfield;
+ unsigned char *temppos;
+ unsigned char *pnp_string;
+ unsigned char end_char;
+
+ int no_more_extensions=0;
+ int stage;
+ int len;
+ unsigned short int checksum;
+ char hex_checksum[5];
+
+ char extension_delims[] = {EndPnP1, EndPnP2, ExtendPnP1, ExtendPnP2, 0};
+ char end_delims[] = {EndPnP1, EndPnP2, 0};
+ unsigned char* p1end = NULL;
+ unsigned char* p2end = NULL;
+
+ /* clear out pnp_id */
+ memset(pnp_id, 0, sizeof(*pnp_id));
+
+ /* copy pnp_string to temp space */
+ pnp_string = alloca(pnp_len+1);
+ memcpy(pnp_string, pnp_id_string, pnp_len+1);
+
+ /* first find the start of the PnP part of string */
+ p1 = memchr( pnp_string, BeginPnP1, pnp_len );
+ p2 = memchr( pnp_string, BeginPnP2, pnp_len );
+
+
+ if (p1) {
+ int p_len = pnp_len - (p1 - pnp_string);
+ p1end = memchr(p1, EndPnP1, p_len);
+ }
+ if (p2) {
+ int p_len = pnp_len - (p2 - pnp_string);
+ p2end = memchr(p2, EndPnP2, p_len);
+ }
+
+ /* use the one which points nearest to start of the string */
+ /* and is actually defined */
+ if ( p1 && p1end && p2 && p2end ) {
+ start = (p1 < p2) ? p1 : p2;
+ } else if ( p1 && p1end )
+ start = p1;
+ else if ( p2 && p2end )
+ start = p2;
+ else
+ start = NULL;
+
+ /* if no start then we're done */
+ if (!start)
+ return -1;
+
+ /* the length of the initial part cannot be more than 17 bytes */
+ if ((start - pnp_string) > 17)
+ return -1;
+
+ /* setup end character we are looking for based on the start character */
+ if (start == p2) {
+ pnp_id->xlate_6bit = 1;
+ end_char = EndPnP2;
+ /* we need to xlate data in PnP fields */
+ /* remember to skip the revision fields (bytes 1 and 2 after start) */
+ temppos=start;
+ while (1) {
+ if (*temppos == EndPnP2) {
+ *temppos += 0x20;
+ break;
+ } else if (temppos != start+1 && temppos != start+2 )
+ *temppos += 0x20;
+
+ temppos++;
+ }
+ } else {
+ pnp_id->xlate_6bit = 0;
+ end_char = EndPnP1;
+ }
+
+ /* move everything before the start of the PnP block */
+ memcpy(pnp_id->other_id, pnp_string, start-pnp_string);
+ pnp_id->other_len = start - pnp_string;
+
+ /* now we get the PnP fields - all were zero'd out above */
+ curpos = start+1;
+ memcpy(pnp_id->pnp_rev,curpos,2); curpos += 2;
+ memcpy(pnp_id->eisa_id,curpos,3); curpos += 3;
+ memcpy(pnp_id->product_id,curpos,4); curpos += 4;
+ /* now we see if have extension fields */
+ no_more_extensions = 0;
+ stage = 0;
+ while (!no_more_extensions) {
+ if (*curpos == ExtendPnP1 || *curpos == ExtendPnP2) {
+ curpos++;
+ endfield = strpbrk(curpos, extension_delims);
+ if (!endfield)
+ return -1;
+ /* if we reached the end of all PnP data, back off */
+ /* cause there is a checksum at the end of extension data */
+ if (*endfield == EndPnP1 || *endfield == EndPnP2)
+ endfield -= 2;
+ } else
+ break;
+
+ len = endfield - curpos;
+ switch (stage) {
+ case 0:
+ if (len != 8 && len != 0 )
+ return -1;
+
+ memcpy(pnp_id->serial_number,curpos,len);
+ curpos += len;
+ break;
+
+ case 1:
+ if (len > 33)
+ return -1;
+ memcpy(pnp_id->class_name, curpos, len);
+ curpos = endfield;
+ break;
+
+ case 2:
+ if (len > 41)
+ return -1;
+ memcpy(pnp_id->driver_id, curpos, len);
+ curpos = endfield;
+ break;
+
+ case 3:
+ if (len > 41)
+ return -1;
+ memcpy(pnp_id->user_name, curpos, len);
+ curpos = endfield;
+ break;
+ }
+ stage++;
+ }
+
+ /* now find the end of all PnP data */
+ end = strpbrk(curpos, end_delims);
+ if (!end)
+ return -1;
+
+ /* if we had any extensions, we expect an checksum */
+ if (stage != 0) {
+ /* copy checksum into struct */
+ memcpy(pnp_id->checksum, curpos, 2);
+
+ /* compute the checksum as the sum of all PnP bytes, excluding */
+ /* the two byte checksum. */
+ checksum = 0;
+ for (temppos=start; temppos <= end; temppos++) {
+ /* skip checksum in calculation */
+ if (temppos == (end-2) || temppos == (end-1))
+ continue;
+ /* dont xlate the revision at start */
+ if (temppos != (start+1) && temppos != (start+2))
+ checksum += *temppos - ((pnp_id->xlate_6bit) ? 0x20 : 0);
+ else
+ checksum += *temppos;
+ }
+ sprintf(hex_checksum, "%.2X", checksum & 0xff);
+ if (strncmp(hex_checksum, pnp_id->checksum, 2))
+ return -1;
+ }
+
+ /* checksum was ok, so we're done */
+ return 0;
+}
+
+static int attempt_pnp_retrieve(int fd, char *pnp_string, int *pnp_strlen, int pnp_stringbuf_size) {
+ int pnp_probe_status;
+ struct pnp_com_id pnp_id;
+ int tried_at_prodding=0, give_up=0;
+
+ DEBUG("Attempting PNP information retrieval\n");
+
+ while (!give_up) {
+ pnp_probe_status = init_pnp_com_seq1(fd);
+ if (pnp_probe_status == PNP_COM_FATAL)
+ return PNP_COM_FATAL;
+ pnp_probe_status = read_pnp_string(fd, pnp_string, pnp_strlen,
+ pnp_stringbuf_size);
+ if (pnp_probe_status == PNP_COM_FAIL) {
+ init_pnp_com_seq2(fd); /* always succeeds */
+
+ pnp_probe_status = read_pnp_string(fd, pnp_string, pnp_strlen,
+ pnp_stringbuf_size);
+ }
+
+ if (*pnp_strlen == 1 && pnp_string[0] == 'M') /* legacy mouse */
+ return PNP_COM_OK;
+ /* see if we got anything useful, if not try AT command */
+ /* to prod device into correct serial params */
+ if (parse_pnp_string( pnp_string, *pnp_strlen, &pnp_id )<0) {
+ DEBUG("That failed.\n");
+ if (!tried_at_prodding) {
+ DEBUG("Prod modem with AT command.\n");
+ write(fd, "AT\r", 3);
+ tried_at_prodding=1;
+ } else
+ give_up = 1;
+ } else
+ return PNP_COM_OK;
+ }
+
+ /* normal PNP detection has failed. */
+ /* try sending a ATI9 code to the modem to see if we get PnP id back */
+ init_pnp_com_ati9(fd);
+ read_pnp_string(fd, pnp_string, pnp_strlen, pnp_stringbuf_size );
+ if (parse_pnp_string( pnp_string, *pnp_strlen, &pnp_id )<0) {
+ *pnp_strlen = 0;
+ pnp_string[0] = 0;
+ return PNP_COM_FAIL;
+ } else
+ return PNP_COM_OK;
+}
+
+struct device *serialProbe(enum deviceClass probeClass, int probeFlags,
+ struct device *devlist) {
+ int fd;
+ int temp;
+ int pnp_strlen;
+ int devicetype=-1;
+ unsigned char pnp_string[100];
+ char port[20];
+ struct termios origattr;
+ struct pnp_com_id pnp_id;
+ struct serialDevice *serdev;
+ struct stat sb;
+ int maj, twelve=12;
+ int console=-1;
+ int stdin_line=-1;
+ struct serial_struct si;
+
+ DEBUG("Probing for serial ports\n");
+
+ if (probeFlags & PROBE_SAFE) return devlist;
+
+ /* Are we on a serial console? */
+ fstat(0,&sb);
+ maj = major(sb.st_rdev);
+ if (maj != 4 && (maj < 136 || maj > 143)) {
+ if (ioctl (0, TIOCLINUX, &twelve) < 0) {
+ if (ioctl (0, TIOCGSERIAL, &si) >= 0) {
+ if (si.line > 0) {
+ stdin_line = 1 << si.line;
+ } else {
+ stdin_line = 0;
+ }
+ } else stdin_line = 0;
+ }
+ }
+
+ fd=open("/dev/console",O_RDWR);
+ if (fd != -1) {
+ fstat(fd,&sb);
+ maj = major(sb.st_rdev);
+ if (maj != 4 && (maj < 136 || maj > 143)) {
+ if (ioctl (fd, TIOCLINUX, &twelve) < 0) {
+ #ifdef __powerpc__
+ // we could have gotten an error for another reason - like EINVAL
+ // skipping ttyS0 on PPC - which is where most modems reside
+ if (errno == ENOTTY) {
+ #endif
+ if (ioctl (fd, TIOCGSERIAL, &si) >= 0) {
+ if (si.line > 0) {
+ console = 1 << si.line;
+ } else {
+ console = 0;
+ #ifdef __powerpc__
+ }
+ #endif
+ }
+ } else console = 0;
+ }
+ }
+ close(fd);
+ }
+
+
+ if (
+ (probeClass & CLASS_UNSPEC) ||
+ (probeClass & CLASS_OTHER) ||
+ (probeClass & CLASS_MOUSE) ||
+ (probeClass & CLASS_MODEM) ||
+ (probeClass & CLASS_PRINTER)
+ ) {
+ int x;
+
+ for (x=0; x<=3 ; x++) {
+ struct stat sbuf;
+ char lockfile[32];
+ if (x==console || x==stdin_line) continue;
+ snprintf(port,20,"/dev/ttyS%d",x);
+
+ /* Make sure it's not in use */
+ snprintf(lockfile,32,"/var/lock/LCK..ttyS%d",x);
+ if (!stat(lockfile,&sbuf)) {
+ DEBUG("Port %s in use, skipping probe.\n",
+ port);
+ continue;
+ }
+ memset(lockfile,'\0',32);
+ if (readlink("/dev/modem",lockfile,32)>0) {
+ if (!strcmp(basename(port),basename(lockfile))) {
+ snprintf(lockfile,32,"/var/lock/LCK..modem");
+ if (!stat(lockfile,&sbuf)) {
+ DEBUG("Port %s in use, skipping probe.\n",
+ port);
+ continue;
+ }
+ }
+ }
+
+ if ((fd=open_serial_port(port)) < 0) {
+ continue;
+ }
+ /* save the current state of the port */
+ temp = tcgetattr(fd, &origattr);
+ if (temp < 0) {
+ DEBUG("unable to retrieve port attributes...no port present?\n");
+ close(fd);
+ continue;
+ }
+
+
+ /* try twiddling RS232 control lines and see if it talks to us */
+ devicetype=-1;
+ pnp_strlen = 0;
+ if (attempt_pnp_retrieve( fd, pnp_string, &pnp_strlen,
+ sizeof(pnp_string) - 1 ) == PNP_COM_FATAL)
+ goto endprobe;
+
+ /* see if we found any PnP signature */
+ if (pnp_strlen != 0 && (pnp_strlen != 1 || pnp_string[0] != 'M')) {
+
+ /* fill in the PnP com structure */
+ if (parse_pnp_string( pnp_string, pnp_strlen, &pnp_id )<0) {
+ DEBUG("Got PNP data back, but failed to parse. Aborting\n");
+ goto endprobe;
+ } else {
+ char *foo;
+ int len;
+
+ DEBUG("PNP data parsed.\n");
+ serdev = serialNewDevice(NULL);
+
+ if (pnp_id.user_name[0]) {
+ serdev->pnpdesc = strdup(pnp_id.user_name);
+ len = strlen(pnp_id.eisa_id) +
+ strlen(pnp_id.product_id) +
+ strlen(pnp_id.user_name) + 3;
+ foo = malloc(len);
+ snprintf(foo,len,"%s|%s %s",pnp_id.eisa_id,
+ pnp_id.product_id,pnp_id.user_name);
+ } else {
+ len = strlen(pnp_id.eisa_id) +
+ strlen(pnp_id.product_id) + 3;
+ foo = malloc(len);
+ snprintf(foo,len,"%s|%s",pnp_id.eisa_id,
+ pnp_id.product_id);
+ }
+ if (serdev->desc) free(serdev->desc);
+ serdev->desc=strdup(foo);
+ serdev->device=strdup(port+5);
+ if (serdev->driver) free(serdev->driver);
+ serdev->driver=strdup("ignore");
+ serdev->pnpmfr = strdup(pnp_id.eisa_id);
+ serdev->pnpmodel = strdup(pnp_id.product_id);
+
+ free(foo);
+ foo=pnp_id.product_id;
+ if (pnp_id.driver_id) {
+ if (strstr(pnp_id.driver_id,"PNP"))
+ foo = strstr(pnp_id.driver_id,"PNP")+3;
+ serdev->pnpcompat = strdup(pnp_id.driver_id);
+ }
+
+ if (*pnp_id.other_id == 'M' ||
+ !strncmp(pnp_id.class_name, "MOUSE", 5) ||
+ !strncmp(foo, "0F", 2)) {
+ serdev->type = CLASS_MOUSE;
+ if (!strncmp(serdev->desc, "|", 1)) {
+ free(serdev->desc);
+ serdev->desc=strdup("Generic Serial Mouse");
+ }
+ if (serdev->driver) free(serdev->driver);
+ serdev->driver = strdup("generic");
+ }
+ else if (!strncmp(pnp_id.class_name, "MODEM", 5) ||
+ !strncmp(foo, "C", 1))
+ serdev->type = CLASS_MODEM;
+ else if (!strncmp(pnp_id.class_name, "PRINTER", 7))
+ serdev->type = CLASS_PRINTER;
+ else
+ serdev->type = CLASS_OTHER;
+ if (serdev->type & probeClass) {
+ if (devlist)
+ serdev->next = devlist;
+ devlist = (struct device *)serdev;
+ if (probeFlags & PROBE_ONE) {
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ return devlist;
+ }
+ } else {
+ serdev->freeDevice(serdev);
+ }
+ goto endprobe;
+ }
+ } else {
+ DEBUG("No PNP data received.\n");
+ /* try to find a legacy device */
+
+ temp = find_legacy_mouse(fd);
+ if (temp == PNP_COM_FATAL) {
+ goto endprobe;
+ } else if (temp == PNP_COM_OK) {
+ if (probeClass & CLASS_MOUSE) {
+ serdev=serialNewDevice(NULL);
+ serdev->type = CLASS_MOUSE;
+ serdev->device = strdup(port+5);
+ serdev->driver= strdup("generic");
+ serdev->desc = strdup("Generic Serial Mouse");
+ if (devlist)
+ serdev->next = devlist;
+ devlist = (struct device *)serdev;
+ if (probeFlags & PROBE_ONE) {
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ return devlist;
+ }
+ }
+ goto endprobe;
+ } else {
+ DEBUG("Didn't see a legacy mouse.\n");
+
+ temp = find_legacy_modem(fd);
+ if (temp == PNP_COM_FATAL) {
+ goto endprobe;
+ } else if (temp == PNP_COM_OK) {
+ DEBUG("Legacy modem signature seen.\n");
+ if (probeClass & CLASS_MODEM) {
+ serdev=serialNewDevice(NULL);
+ serdev->type = CLASS_MODEM;
+ serdev->device = strdup(port+5);
+ serdev->driver= strdup("ignore");
+ serdev->desc = strdup("Generic Serial Modem");
+ if (devlist)
+ serdev->next = devlist;
+ devlist = (struct device *)serdev;
+ if (probeFlags & PROBE_ONE) {
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ return devlist;
+ }
+ }
+ goto endprobe;
+ } else {
+ DEBUG("Didnt see a legacy modem, game over.\n");
+ }
+ }
+ }
+ endprobe:
+ DEBUG("Restoring original port attributes\n");
+ tcsetattr(fd, TCSANOW, &origattr);
+ tcflush(fd, TCIOFLUSH);
+ close(fd);
+ }
+ }
+ return devlist;
+}
diff --git a/tools/serial_probe/serial.h b/tools/serial_probe/serial.h
new file mode 100644
index 000000000..691abeb26
--- /dev/null
+++ b/tools/serial_probe/serial.h
@@ -0,0 +1,43 @@
+/* Copyright 1999-2003 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _KUDZU_SERIAL_H_
+#define _KUDZU_SERIAL_H_
+
+#include "device.h"
+
+struct serialDevice {
+ /* common fields */
+ struct device *next; /* next device in list */
+ int index;
+ enum deviceClass type; /* type */
+ enum deviceBus bus; /* bus it's attached to */
+ char * device; /* device file associated with it */
+ char * driver; /* driver to load, if any */
+ char * desc; /* a description */
+ int detached;
+ /* serial-specific fields */
+ struct serialDevice *(*newDevice) (struct serialDevice *dev);
+ void (*freeDevice) (struct serialDevice *dev);
+ void (*writeDevice) (FILE *file, struct serialDevice *dev);
+ int (*compareDevice) (struct serialDevice *dev1, struct serialDevice *dev2);
+ char * pnpmfr;
+ char * pnpmodel;
+ char * pnpcompat;
+ char * pnpdesc;
+
+};
+
+struct serialDevice *serialNewDevice(struct serialDevice *dev);
+struct device *serialProbe(enum deviceClass probeClass, int probeFlags,
+ struct device *devlist);
+
+#endif
diff --git a/tools/serial_probe/serial_probe.c b/tools/serial_probe/serial_probe.c
new file mode 100644
index 000000000..a9aae52e5
--- /dev/null
+++ b/tools/serial_probe/serial_probe.c
@@ -0,0 +1,114 @@
+/* Copyright 1999 Mandrakesoft <fpons@mandrakesoft.com>
+ *
+ * The following file used by this one are copyrighted by RedHat and
+ * are taken from kudzu :
+ * device.h
+ * serial.h
+ * serial.c
+ * This file is taken from kudzu.c copyrighted by RedHat, 1999.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "serial.h"
+#include "device.h"
+
+typedef struct device *(newFunc)(struct device *);
+typedef int (initFunc)();
+typedef struct device *(probeFunc)(enum deviceClass, int, struct device *);
+
+char *classStrings[] = {
+ "UNSPEC", "OTHER", "NETWORK", "SCSI", "VIDEO", "AUDIO",
+ "MOUSE", "MODEM", "CDROM", "TAPE", "FLOPPY", "SCANNER",
+ "HD", "RAID", "PRINTER", "CAPTURE", "KEYBOARD", NULL
+};
+
+struct device *newDevice(struct device *old, struct device *new) {
+ if (!old) {
+ if (!new) {
+ new = malloc(sizeof(struct device));
+ memset(new,'\0',sizeof(struct device));
+ }
+ new->type = CLASS_UNSPEC;
+ } else {
+ new->type = old->type;
+ if (old->device) new->device = strdup(old->device);
+ if (old->driver) new->driver = strdup(old->driver);
+ if (old->desc) new->desc = strdup(old->desc);
+ }
+ new->newDevice = newDevice;
+ new->freeDevice = freeDevice;
+ new->compareDevice = compareDevice;
+ return new;
+}
+
+void freeDevice(struct device *dev) {
+ if (!dev) {
+ printf("freeDevice(null)\n");
+ abort(); /* return; */
+ }
+ if (dev->device) free (dev->device);
+ if (dev->driver) free (dev->driver);
+ if (dev->desc) free (dev->desc);
+ free (dev);
+}
+
+void writeDevice(FILE *file, struct device *dev) {}
+int compareDevice(struct device *dev1, struct device *dev2) { return 0; }
+
+int main () {
+ struct device* devices = NULL;
+ struct serialDevice* serialDevice = NULL;
+
+ devices = serialProbe(CLASS_UNSPEC, 0, devices);
+ while (devices) {
+ serialDevice = (struct serialDevice*)devices;
+
+ printf("CLASS=");
+ if (serialDevice->type == CLASS_UNSPEC) puts("UNSPEC"); else
+ if (serialDevice->type == CLASS_OTHER) puts("OTHER"); else
+ if (serialDevice->type == CLASS_NETWORK) puts("NETWORK"); else
+ if (serialDevice->type == CLASS_SCSI) puts("SCSI"); else
+ if (serialDevice->type == CLASS_MOUSE) puts("MOUSE"); else
+ if (serialDevice->type == CLASS_AUDIO) puts("AUDIO"); else
+ if (serialDevice->type == CLASS_CDROM) puts("CDROM"); else
+ if (serialDevice->type == CLASS_MODEM) puts("MODEM"); else
+ if (serialDevice->type == CLASS_VIDEO) puts("VIDEO"); else
+ if (serialDevice->type == CLASS_TAPE) puts("TAPE"); else
+ if (serialDevice->type == CLASS_FLOPPY) puts("FLOPPY"); else
+ if (serialDevice->type == CLASS_SCANNER) puts("SCANNER"); else
+ if (serialDevice->type == CLASS_HD) puts("HD"); else
+ if (serialDevice->type == CLASS_RAID) puts("RAID"); else
+ if (serialDevice->type == CLASS_PRINTER) puts("PRINTER"); else
+ if (serialDevice->type == CLASS_CAPTURE) puts("CAPTURE"); else
+ if (serialDevice->type == CLASS_KEYBOARD) puts("KEYBOARD"); else
+ if (serialDevice->type == CLASS_MONITOR) puts("MONITOR"); else
+ if (serialDevice->type == CLASS_USB) puts("USB"); else
+ if (serialDevice->type == CLASS_SOCKET) puts("SOCKET"); else
+ if (serialDevice->type == CLASS_FIREWIRE) puts("FIREWIRE"); else
+ if (serialDevice->type == CLASS_IDE) puts("IDE");
+ printf("BUS=SERIAL\n");
+ printf("DEVICE=/dev/%s\n", serialDevice->device);
+ printf("DRIVER=%s\n", serialDevice->driver);
+ if (!serialDevice->pnpdesc) printf("DESCRIPTION=%s\n", serialDevice->desc);
+ if (serialDevice->pnpmfr) printf("MANUFACTURER=%s\n", serialDevice->pnpmfr);
+ if (serialDevice->pnpmodel) printf("MODEL=%s\n", serialDevice->pnpmodel);
+ if (serialDevice->pnpcompat) printf("COMPAT=%s\n", serialDevice->pnpcompat);
+ if (serialDevice->pnpdesc) printf("DESCRIPTION=%s\n", serialDevice->pnpdesc);
+ printf("\n");
+
+ devices=devices->next;
+ }
+
+ return 0;
+}
diff --git a/tools/shift_all.pl b/tools/shift_all.pl
new file mode 100644
index 000000000..88abfa0e1
--- /dev/null
+++ b/tools/shift_all.pl
@@ -0,0 +1,113 @@
+use MDK::Common;
+
+my %shifts = (
+'af' => 1,
+'am' => 1,
+'ar' => 0,
+'az' => 1,
+'be' => 2,
+'bg' => 2,
+'bn' => 1,
+'br' => 2,
+'bs' => 2,
+'ca' => 2,
+'cs' => 2,
+'cy' => 2,
+'da' => 2,
+'de' => 2,
+'el' => 2,
+'en_GB' => 2,
+'en_US' => 2,
+'eo' => 2,
+'es' => 2,
+'et' => 2,
+'eu' => 2,
+'fa' => 0,
+'fi' => 1,
+'fo' => 2,
+'fr' => 2,
+'ga' => 2,
+'gd' => 2,
+'gl' => 2,
+'gv' => 2,
+'he' => 0,
+'hi' => 1,
+'hr' => 2,
+'hu' => 2,
+'hy' => 1,
+'ia' => 2,
+'id' => 1,
+'is' => 1,
+'it' => 1,
+'iu' => 1,
+'ja' => 3,
+'ka' => 1,
+'kn' => 1,
+'ko' => 1,
+'kw' => 0,
+'lo' => 0,
+'lt' => 0,
+'lv' => 0,
+'mi' => 0,
+'mk' => 0,
+'mn' => 0,
+'mr' => 0,
+'ms' => 0,
+'mt' => 0,
+'nb' => 0,
+'nl' => 0,
+'nn' => 0,
+'no' => 0,
+'oc' => 0,
+'pl' => 0,
+'pt_BR' => 0,
+'pt' => 0,
+'ro' => 0,
+'ru' => 0,
+'sk' => 0,
+'sl' => 0,
+'sp' => 0,
+'sq' => 0,
+'sr' => 0,
+'sv' => 0,
+'ta' => 1,
+'te' => 1,
+'tg' => 0,
+'th' => 0,
+'tr' => 0,
+'tt' => 1,
+'uk' => 0,
+'ur' => 1,
+'uz' => 0,
+'vi' => 0,
+'wa' => 0,
+'yi' => 0,
+'zh_CN' => 0,
+'zh_TW' => 0,
+);
+
+foreach (glob("lang*.png")) {
+ /lang-(.*)\.png/;
+ exists $shifts{$1} or die "doesn't exist for $_";
+ $shifts{$1} or next;
+ print "./a.out $_ l.png $shifts{$1}\n";
+ system("./a.out $_ l.png $shifts{$1}");
+ renamef('l.png', $_);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/shift_img.c b/tools/shift_img.c
new file mode 100644
index 000000000..36cb53e48
--- /dev/null
+++ b/tools/shift_img.c
@@ -0,0 +1,165 @@
+/*
+ * Guillaume Cottenceau (gc at mandriva.com)
+ *
+ * Copyright 2002-2005 Mandriva
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#define PNG_DEBUG 3
+#include <png.h>
+
+void abort_(const char * s, ...)
+{
+ va_list args;
+ va_start(args, s);
+ vfprintf(stderr, s, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ abort();
+}
+
+int x, y;
+
+int width, height;
+png_byte color_type;
+png_byte bit_depth;
+
+png_structp png_ptr;
+png_infop info_ptr;
+int number_of_passes;
+png_bytep * row_pointers;
+
+void read_png_file(char* file_name)
+{
+ char header[8]; // 8 is the maximum size that can be checked
+
+ /* open file and test for it being a png */
+ FILE *fp = fopen(file_name, "rb");
+ if (!fp)
+ abort_("[read_png_file] File %s could not be opened for reading", file_name);
+ fread(header, 1, 8, fp);
+ if (png_sig_cmp(header, 0, 8))
+ abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
+
+
+ /* initialize stuff */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (!png_ptr)
+ abort_("[read_png_file] png_create_read_struct failed");
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ abort_("[read_png_file] png_create_info_struct failed");
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[read_png_file] Error during init_io");
+
+ png_init_io(png_ptr, fp);
+ png_set_sig_bytes(png_ptr, 8);
+
+ png_read_info(png_ptr, info_ptr);
+
+ width = info_ptr->width;
+ height = info_ptr->height;
+ color_type = info_ptr->color_type;
+ bit_depth = info_ptr->bit_depth;
+
+ number_of_passes = png_set_interlace_handling(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
+
+
+ /* read file */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[read_png_file] Error during read_image");
+
+ row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
+ for (y=0; y<height; y++)
+ row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
+
+ png_read_image(png_ptr, row_pointers);
+}
+
+
+void write_png_file(char* file_name)
+{
+ /* create file */
+ FILE *fp = fopen(file_name, "wb");
+ if (!fp)
+ abort_("[write_png_file] File %s could not be opened for writing", file_name);
+
+
+ /* initialize stuff */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (!png_ptr)
+ abort_("[write_png_file] png_create_write_struct failed");
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ abort_("[write_png_file] png_create_info_struct failed");
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during init_io");
+
+ png_init_io(png_ptr, fp);
+
+
+ /* write header */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during writing header");
+
+ png_set_IHDR(png_ptr, info_ptr, width, height,
+ bit_depth, color_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_write_info(png_ptr, info_ptr);
+
+
+ /* write bytes */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during writing bytes");
+
+ png_write_image(png_ptr, row_pointers);
+
+
+ /* end write */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ abort_("[write_png_file] Error during end of write");
+
+ png_write_end(png_ptr, NULL);
+
+}
+
+void process_file(char* shift)
+{
+ int shift_ = atoi(shift);
+
+ if (info_ptr->color_type != PNG_COLOR_TYPE_RGBA)
+ abort_("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (is %d)", info_ptr->color_type);
+
+ width -= shift_;
+ for (y=0; y<height; y++) {
+ row_pointers[y] += 4 * shift_;
+ }
+
+}
+
+
+int main(int argc, char **argv)
+{
+ if (argc != 4)
+ abort_("Usage: program_name <file_in> <file_out> <shift>");
+
+ read_png_file(argv[1]);
+ process_file(argv[3]);
+ write_png_file(argv[2]);
+}
diff --git a/tools/simplify-drakx-modules b/tools/simplify-drakx-modules
new file mode 100755
index 000000000..ec8df1e76
--- /dev/null
+++ b/tools/simplify-drakx-modules
@@ -0,0 +1,5 @@
+#!/usr/bin/perl -pi
+
+s/^\s*use\s+(diagnostics|strict|vars|warnings).*//g;
+
+/^__END__/ and $_ = '', close ARGV;
diff --git a/tools/specific_arch b/tools/specific_arch
new file mode 100755
index 000000000..a86b7bc43
--- /dev/null
+++ b/tools/specific_arch
@@ -0,0 +1,9 @@
+#!/usr/bin/perl
+
+use MDK::Common;
+
+print join(' ', map {
+ my $arch = arch();
+ $arch = $compat_arch{$arch} while $arch && !-e "$_.$arch";
+ -e "$_.$arch" ? "$_.$arch" : ();
+ } @ARGV), "\n";
diff --git a/tools/xhost+.c b/tools/xhost+.c
new file mode 100644
index 000000000..58781274e
--- /dev/null
+++ b/tools/xhost+.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+#include <X11/Xlib.h>
+
+
+int main(int argc, char **argv) {
+ Display *d = XOpenDisplay(getenv("DISPLAY") ? getenv("DISPLAY") : ":0");
+ if (d == NULL) exit(1);
+ XDisableAccessControl(d);
+ XCloseDisplay(d);
+ exit(0);
+}