Commit e7a497f8 authored by Russ Fish's avatar Russ Fish

First installment of cygwinxp support.

parent 3f1d56ac
......@@ -1542,6 +1542,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/linux9/GNUmakefile tmcd/linux9/supfile \
tmcd/freebsd5/GNUmakefile tmcd/freebsd5/supfile \
tmcd/openbsd/GNUmakefile tmcd/ron/GNUmakefile tmcd/plab/GNUmakefile \
tmcd/cygwinxp/GNUmakefile \
utils/GNUmakefile utils/vlandiff utils/vlansync utils/delay_config \
utils/sshtb utils/create_image utils/node_admin utils/webcreateimage \
utils/firstuser utils/export_tables utils/eventping \
......
......@@ -29,6 +29,7 @@ CFLAGS += -DETCDIR='"$(INSTALL_ETCDIR)"'
SSLFLAGS = -DWITHSSL
TMLIBS += -lssl -lcrypto
SSLOBJ = ssl.o
ifeq ($(SYSTEM),Linux)
RHLVERSION := $(shell cat /etc/redhat-release | sed -e 's/Red Hat Linux release \([0-9]\).*/Linux\1/')
NEEDKERB := $(shell nm /usr/lib/libssl.a | grep -q krb; echo $$?)
......@@ -43,6 +44,7 @@ else
MDSUBDIR = linux
endif
endif
ifeq ($(SYSTEM),FreeBSD)
FBSDVERSION := $(shell uname -v | sed -e 's/FreeBSD \([0-9]\).*/FreeBSD\1/')
ifeq ($(FBSDVERSION),FreeBSD5)
......@@ -52,6 +54,11 @@ MDSUBDIR = freebsd
endif
endif
ifeq ($(SYSTEM),CYGWIN_NT-5.1)
# Cygwin on Windows XP (a.k.a. NT 5.1) - resembles the Linux case.
MDSUBDIR = cygwinxp
endif
ifeq ($(EVENTSYS),1)
TMCDCFLAGS = `elvin-config --cflags vin4c` \
-I$(TESTBED_SRCDIR)/event/lib -DEVENTSYS
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
#
# XXX ONLY RUN THIS INSTALL ON A CYGWIN / WINDOWS XP NODE!
# Similar to linux9, cygwinxp is an overlay on linux, which is an overlay on common.
#
# Trivial. These things just need to be installed into the right place
# on a testbed node before cutting an image.
#
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = tmcd/cygwinxp
include $(OBJDIR)/Makeconf
SCRIPTS =
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(SCRIPTS)
include $(TESTBED_SRCDIR)/GNUmakerules
DESTDIR =
SYSETCDIR = $(DESTDIR)/etc
ETCDIR = $(DESTDIR)$(CLIENT_ETCDIR)
BINDIR = $(DESTDIR)$(CLIENT_BINDIR)
VARDIR = $(DESTDIR)$(CLIENT_VARDIR)
RCDIR = $(SYSETCDIR)/rc.d
INSTALL = /usr/bin/install -c
COMMON = $(SRCDIR)/../common
install client-install: baselinux-install common-install etc-install \
sup-install script-install bin-install
@echo "Remember to install the PEM files if necessary"
simple-install: common-install script-install bin-install
dir-install:
baselinux-install: dir-install
(cd ../linux; $(MAKE) client-install)
rm -f $(BINDIR)/rc/rc.healthd
rm -f $(BINDIR)/rc/rc.slothd
common-install: dir-install
(cd ../common; $(MAKE) local-install)
sup-install: dir-install
bin-install: dir-install
etc-install: dir-install sysetc-remove sysetc-install
sysetc-install: dir-install ###ifcfgs
sysetc-remove:
script-install: dir-install $(SCRIPTS)
$(INSTALL) -m 755 $(SRCDIR)/rc.cygwinxp-user $(BINDIR)/rc/rc.cygwinxp-user
$(INSTALL) -m 755 $(SRCDIR)/rc.cygwinxp $(BINDIR)/rc/rc.cygwinxp
$(INSTALL) -m 755 $(SRCDIR)/liblocsetup.pm $(BINDIR)/liblocsetup.pm
$(INSTALL) -m 755 $(SRCDIR)/emount $(BINDIR)/emount
$(INSTALL) -m 755 $(SRCDIR)/eumount $(BINDIR)/eumount
sfs-install:
# create ifcfg-eth? files
ifcfgs: $(SRCDIR)/mkifcfgs $(SRCDIR)/ifcfg.template
$(SRCDIR)/mkifcfgs $(SRCDIR)/ifcfg.template
#!/usr/bin/perl -w
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
#
# Emulab NFS mount command, called by rc.mounts .
#
# Args are the remote and local mount points, for example:
# eumount fs.emulab.net:/q/proj/testbed /proj/testbed
# With no args, reports the current mounts with "net use".
#
# Since this is Windows, mounts go through drive letters, like this:
# S: \\fs.emulab.net\share # Share
# P: \\fs.emulab.net\q\proj\testbed # Project
# Q: \\fs.emulab.net\groups\testbed\TG1 # Group
# H: \\fs.emulab.net\users\fish # Creator
# I: \\fs.emulab.net\users\mike # Swapper
#
# Creator/swapper information comes from tmcc via TMCREATOR()/TMSWAPPER() files.
# Any other user mounts require specifying the drive letter with the -d option.
#
# The Services For Unix (SFU 3.5) NFS client commands are used underneath,
# and CygWin symlinks are made to point to the /cygdrive/driveletter mount,
# completing the Unix-like illusion.
sub usage()
{
print "Usage: emount [-v] [-d driveletter:] remotehost:path localpath\n";
print " or: emount\n";
exit(1);
}
my $optlist = "vd:";
my $verbose = 0;
my $driveletter = "";
my $remote = "";
my $local = "";
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
#
use libsetup;
use liblocsetup;
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the positional arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"v"})) {
$verbose = 1;
}
if (defined($options{"d"})) {
$driveletter = $options{"d"};
}
if (@ARGV == 0 ) {
system("$NET use");
exit(0);
}
elsif (@ARGV == 2) {
$remote = $ARGV[0];
$local = $ARGV[1];
}
else {
usage();
}
my $cmd;
# Infer the drive letter from what's being mounted.
my($project, $group, $user);
$driveletter = "S:"
if (!$driveletter && $remote =~ m|:/share$|);
$driveletter = "P:"
if (!$driveletter && (($project) = ($remote =~ m|:/q/proj/([-[:alnum:]]+)$|)) );
$driveletter = "Q:"
if (!$driveletter && (($project, $group) =
($remote =~ m|:/q/proj/([-[:alnum:]]+)/([-[:alnum:]]+)$|)) );
if (!$driveletter && (($user) = ($remote =~ m|:/users/([-[:alnum:]]+)|))) {
my $tmcreator = TMCREATOR();
my $tmswapper = TMSWAPPER();
my $creator = `cat $tmcreator`;
my $swapper = `cat $tmswapper`;
$creator =~ s/\n//;
$swapper =~ s/\n//;
##print "user '$user', creator '$creator', swapper '$swapper'\n";
$driveletter = "H:"
if ($user eq $creator);
$driveletter = "I:"
if (!$driveletter && $user eq $swapper);
}
print "Using drive letter $driveletter\n"
if ($verbose && $driveletter);
if (!$driveletter) {
print STDERR "emount: Must specify a drive letter.\n";
exit(1);
}
# Make sure that mount persistence is off.
os_noisycmd("$NET use /persistent:no", 0);
# Mount onto a drive letter using the Services For Unix NFS client.
print "Mounting remote directory '$remote' on drive letter '$driveletter'.\n"
if ($verbose);
$cmd = "$SFCMOUNT $remote $driveletter";
if (os_noisycmd($cmd, $verbose) != 0) {
print STDERR "emount: Failed SFU mount, $cmd.\n";
exit(1);
}
# Make the CygWin symlink from the local path to the driveletter automount point.
my $localdir = $local;
$localdir =~ s|(.*)/.*|$1|;
my $cygdrive = "/cygdrive/" . lc(substr($driveletter, 0, 1));
if (length($localdir) && ! -e $localdir) {
print "Making CygWin '$localdir' directory to contain symlinks.\n"
if ($verbose);
if (! os_mkdir($localdir, "0777")) { # Writable so anybody can make symlinks.
print STDERR "emount: Failed CygWin mkdir, $cmd.\n";
exit(1);
}
}
if (-e $local) {
print "Removing previous CygWin symlink '$local'.\n"
if ($verbose);
$cmd = "$CHOWN `id -un` $local";
if (system($cmd) != 0) {
print STDERR "emount: Failed to take ownership of symlink, $cmd.\n";
}
$cmd = "$RM -f $local";
if (system($cmd) != 0) {
print STDERR "emount: Failed to remove previous CygWin symlink, $cmd.\n";
exit(1);
}
}
print "Making CygWin symlink '$local' to '$cygdrive'.\n"
if ($verbose);
$cmd = "$LN -f -s $cygdrive $local";
if (system($cmd) != 0) {
print STDERR "emount: Failed CygWin symlink, $cmd.\n";
exit(1);
}
exit(0);
#!/usr/bin/perl -w
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
#
# Emulab NFS unmount command, called by rc.mounts . See emount for more info.
#
# Arg is the local mount points, for example:
# eumount /proj/testbed
#
# The Services For Unix (SFU 3.5) NFS client commands are used underneath, and the
# CygWin symlink pointing to the /cygdrive/driveletter mount are cleaned up.
sub usage()
{
print "Usage: eumount [-v] localpath\n";
exit(1);
}
my $optlist = "v";
my $verbose = 0;
my $local = "";
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself.
#
use libsetup;
use liblocsetup;
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the positional arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"v"})) {
$verbose = 1;
}
if (@ARGV == 1) {
$local = $ARGV[0];
}
else {
usage();
}
my(%curmounts, $cmd);
if (os_getnfsmountpoints(\%curmounts) < 0) {
fatal("Could not get current NFS mounts!");
}
if (!defined($curmounts{$local})) {
print STDERR "eumount: $local is not mounted.\n";
exit(1);
}
else {
my $rpath = $curmounts{$local}[0];
my $driveletter = $curmounts{$local}[1];
# Unmount from a drive letter using the Services For Unix NFS client.
print "Unmounting remote '$rpath' from drive letter '$driveletter'.\n"
if ($verbose);
$cmd = "$SFCUMOUNT $driveletter";
if (os_noisycmd($cmd, $verbose) != 0) {
print STDERR "eumount: Failed SFU umount, $cmd.\n";
exit(1);
}
# Kill the CygWin symlink from the local path to the driveletter automount point.
print "Removing CygWin symlink '$local'.\n"
if ($verbose);
$cmd = "$RM $local";
if (system($cmd) != 0) {
print STDERR "emount: Failed to remove CygWin symlink, $cmd.\n";
exit(1);
}
}
exit(0);
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
#
# Linux specific routines and constants for the client bootime setup stuff.
#
package liblocsetup;
use Exporter;
@ISA = "Exporter";
@EXPORT =
qw ( $CP $LN $RM $CHOWN $EGREP
$NFSMOUNT $UMOUNT $SFCMOUNT $SFCUMOUNT $NTS $NET
$TMPASSWD $SFSSD $SFSCD $RPMCMD
os_account_cleanup os_ifconfig_line os_etchosts_line
os_setup os_groupadd os_useradd os_userdel os_usermod os_mkdir
os_ifconfig_veth
os_routing_enable_forward os_routing_enable_gated
os_routing_add_manual os_routing_del_manual os_homedirdel
os_groupdel os_getnfsmounts os_getnfsmountpoints os_noisycmd
os_fwconfig_line os_fwrouteconfig_line
);
# Must come after package declaration!
use English;
# Load up the paths. Its conditionalized to be compatabile with older images.
# Note this file has probably already been loaded by the caller.
BEGIN
{
if (-e "/etc/emulab/paths.pm") {
require "/etc/emulab/paths.pm";
import emulabpaths;
}
else {
my $ETCDIR = "/etc/rc.d/testbed";
my $BINDIR = "/etc/rc.d/testbed";
my $VARDIR = "/etc/rc.d/testbed";
my $BOOTDIR = "/etc/rc.d/testbed";
}
}
#
# Various programs and things specific to Linux and that we want to export.
#
$CP = "/bin/cp";
$LN = "/bin/ln";
$RM = "/bin/rm";
$CHOWN = "/bin/chown";
$EGREP = "/bin/egrep -q";
# Emulab wrappers for Windows.
$NFSMOUNT = "$BINDIR/emount";
$UMOUNT = "$BINDIR/eumount";
$MKPASSWD = "/bin/mkpasswd";
$MKGROUP = "/bin/mkgroup";
$AWK = "/bin/gawk";
$CYGMOUNT = "/bin/mount";
$CYGUOUNT = "/bin/umount";
$SFC = "/cygdrive/c/SFU/common";
$SFCMOUNT = "$SFC/mount";
$SFCUMOUNT = "$SFC/umount";
$NTS = "/cygdrive/c/WINDOWS/system32";
$NET = "$NTS/net";
$BASH = "/bin/bash";
#
# These are not exported
#
my $USERADD = "/usr/sbin/useradd";
my $USERDEL = "/usr/sbin/userdel";
my $USERMOD = "/usr/sbin/usermod";
my $GROUPADD = "/usr/sbin/groupadd";
my $GROUPDEL = "/usr/sbin/groupdel";
my $IFCONFIGBIN = "/sbin/ifconfig";
my $IFCONFIG = "$IFCONFIGBIN %s inet %s netmask %s";
my $IFC_1000MBS = "1000baseTx";
my $IFC_100MBS = "100baseTx";
my $IFC_10MBS = "10baseT";
my $IFC_FDUPLEX = "FD";
my $IFC_HDUPLEX = "HD";
my @LOCKFILES = ("/etc/group.lock", "/etc/gshadow.lock");
my $MKDIR = "/bin/mkdir";
my $GATED = "/usr/sbin/gated";
my $ROUTE = "/sbin/route";
my $SHELLS = "/etc/shells";
my $DEFSHELL = "/bin/tcsh";
#
# OS dependent part of cleanup node state.
#
sub os_account_cleanup()
{
unlink @LOCKFILES;
# Generate the CygWin password and group files from the registry users.
# Make root's UID zero.
printf STDOUT "Resetting passwd and group files\n";
if (system("$MKPASSWD -l | \
$AWK -F: '/^root:/{\$3=\"0\"} {OFS=\":\"; print}' > /etc/passwd") != 0) {
print STDERR "Could not generate /etc/password file: $!\n";
return -1;
}
# Make wheel an alias for Administrators.
if (system("mkgroup -l | \
$AWK '/^Administrators:/{print \"wheel\" substr(\$0, index(\$0,\":\"))} \
{print}' > /etc/group") != 0) {
print STDERR "Could not generate /etc/group file: $!\n";
return -1;
}
return 0;
}
#
# Generate and return an ifconfig line that is approriate for putting
# into a shell script (invoked at bootup).
#
sub os_ifconfig_line($$$$$$$;$$)
{
my ($iface, $inet, $mask, $speed, $duplex, $aliases,
$iface_type, $settings, $rtabid) = @_;
my ($miirest, $miisleep, $miisetspd, $media);
my ($uplines, $downlines);
#
# Special handling for new style interfaces (which have settings).
# This should all move into per-type modules at some point.
#
if (defined($settings) && exists($settings->{"protocol"}) &&
$settings->{"protocol"} ne "ethernet") {
#
# Setting the protocol is special and appears to be card specific.
# How stupid is that!
#
my $protocol = $settings->{"protocol"};
my $privcmd = "";
if ($iface_type eq "ath") {
$privcmd = "/sbin/iwpriv $iface mode ";
SWITCH1: for ($protocol) {
/^80211a$/ && do {
$privcmd .= "1";
last SWITCH1;
};
/^80211b$/ && do {
$privcmd .= "2";
last SWITCH1;
};
/^80211g$/ && do {
$privcmd .= "3";
last SWITCH1;
};
}
}
else {
warn("*** WARNING: Unsupported interface type $iface_type!\n");
return undef;
}
#
# At the moment, we expect just the various flavors of 80211, and
# we treat them all the same, configuring with iwconfig and iwpriv.
#
my $iwcmd = "/sbin/iwconfig $iface ";
#
# We demand to be given an ssid.
#
if (!exists($settings->{"ssid"})) {
warn("*** WARNING: No SSID provided for $iface!\n");
return undef;
}
$iwcmd .= "essid ". $settings->{"ssid"};
# If we do not get a channel, pick one.
if (exists($settings->{"channel"})) {
$iwcmd .= " channel " . $settings->{"channel"};
}
else {
$iwcmd .= " channel 3";
}
# txpower and rate default to auto if not specified.
if (exists($settings->{"rate"})) {
$iwcmd .= " rate " . $settings->{"rate"};
}
else {
$iwcmd .= " rate auto";
}
if (exists($settings->{"txpower"})) {
$iwcmd .= " txpower " . $settings->{"txpower"};
}
else {
$iwcmd .= " txpower auto";
}
# Allow this too.
if (exists($settings->{"sensitivity"})) {
$iwcmd .= " sens " . $settings->{"sensitivity"};
}
#
# We demand to be told if we are the master or a peon.
# This needs to be last for some reason.
#
if (!exists($settings->{"accesspoint"})) {
warn("*** WARNING: No accesspoint provided for $iface!\n");
return undef;
}
my $accesspoint = $settings->{"accesspoint"};
my $accesspointwdots;
# Allow either dotted or undotted notation!
if ($accesspoint =~ /^(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})$/) {
$accesspointwdots = "$1:$2:$3:$4:$5:$6";
}
elsif ($accesspoint =~
/^(\w{2}):(\w{2}):(\w{2}):(\w{2}):(\w{2}):(\w{2})$/) {
$accesspointwdots = $accesspoint;
$accesspoint = "${1}${2}${3}${4}${5}${6}";
}
else {
warn("*** WARNING: Improper format for MAC ($accesspoint) ".
"provided for $iface!\n");
return undef;
}
if (libsetup::findiface($accesspoint) eq $iface) {
$iwcmd .= " mode Master";
}
else {
$iwcmd .= " mode Managed ap $accesspointwdots";
}
$uplines = sprintf($IFCONFIG, $iface, $inet, $mask) . "\n";
$uplines .= $privcmd . "\n";
$uplines .= $iwcmd;
$downlines = "$IFCONFIGBIN $iface down";
return ($uplines, $downlines);
}
#
# Need to check units on the speed. Just in case.
#