From e7a497f89f6badae3da6f4139f60763518927d49 Mon Sep 17 00:00:00 2001 From: Russ Fish <fish@flux.utah.edu> Date: Mon, 25 Oct 2004 18:10:58 +0000 Subject: [PATCH] First installment of cygwinxp support. --- configure | 1 + tmcd/GNUmakefile.in | 7 + tmcd/cygwinxp/GNUmakefile.in | 78 ++++ tmcd/cygwinxp/emount | 164 ++++++++ tmcd/cygwinxp/eumount | 95 +++++ tmcd/cygwinxp/liblocsetup.pm | 675 +++++++++++++++++++++++++++++++++ tmcd/cygwinxp/profile | 77 ++++ tmcd/cygwinxp/rc.cygwinxp | 19 + tmcd/cygwinxp/rc.cygwinxp-user | 40 ++ 9 files changed, 1156 insertions(+) create mode 100644 tmcd/cygwinxp/GNUmakefile.in create mode 100755 tmcd/cygwinxp/emount create mode 100755 tmcd/cygwinxp/eumount create mode 100644 tmcd/cygwinxp/liblocsetup.pm create mode 100755 tmcd/cygwinxp/profile create mode 100755 tmcd/cygwinxp/rc.cygwinxp create mode 100644 tmcd/cygwinxp/rc.cygwinxp-user diff --git a/configure b/configure index 513e86754d..8242e55e06 100755 --- a/configure +++ b/configure @@ -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 \ diff --git a/tmcd/GNUmakefile.in b/tmcd/GNUmakefile.in index b1038ad4fd..9add9d6f4a 100644 --- a/tmcd/GNUmakefile.in +++ b/tmcd/GNUmakefile.in @@ -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 diff --git a/tmcd/cygwinxp/GNUmakefile.in b/tmcd/cygwinxp/GNUmakefile.in new file mode 100644 index 0000000000..4d3bb00e5c --- /dev/null +++ b/tmcd/cygwinxp/GNUmakefile.in @@ -0,0 +1,78 @@ +# +# 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 diff --git a/tmcd/cygwinxp/emount b/tmcd/cygwinxp/emount new file mode 100755 index 0000000000..1a39a3a1e6 --- /dev/null +++ b/tmcd/cygwinxp/emount @@ -0,0 +1,164 @@ +#!/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); + diff --git a/tmcd/cygwinxp/eumount b/tmcd/cygwinxp/eumount new file mode 100755 index 0000000000..82abe51911 --- /dev/null +++ b/tmcd/cygwinxp/eumount @@ -0,0 +1,95 @@ +#!/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); + diff --git a/tmcd/cygwinxp/liblocsetup.pm b/tmcd/cygwinxp/liblocsetup.pm new file mode 100644 index 0000000000..8bafebac2b --- /dev/null +++ b/tmcd/cygwinxp/liblocsetup.pm @@ -0,0 +1,675 @@ +#!/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. + # + if ($speed =~ /(\d*)([A-Za-z]*)/) { + if ($2 eq "Mbps") { + $speed = $1; + } + elsif ($2 eq "Kbps") { + $speed = $1 / 1000; + } + else { + warn("*** Bad speed units $2 in ifconfig, default to 100Mbps\n"); + $speed = 100; + } + if ($speed == 1000) { + $media = $IFC_1000MBS; + } + elsif ($speed == 100) { + $media = $IFC_100MBS; + } + elsif ($speed == 10) { + $media = $IFC_10MBS; + } + else { + warn("*** Bad Speed $speed in ifconfig, default to 100Mbps\n"); + $speed = 100; + $media = $IFC_100MBS; + } + } + if ($duplex eq "full") { + $media = "$media-$IFC_FDUPLEX"; + } + elsif ($duplex eq "half") { + $media = "$media-$IFC_HDUPLEX"; + } + else { + warn("*** Bad duplex $duplex in ifconfig, default to full\n"); + $duplex = "full"; + $media = "$media-$IFC_FDUPLEX"; + } + + # + # Linux is apparently changing from mii-tool to ethtool but some drivers + # don't support the new interface (3c59x), some don't support the old + # interface (e1000), and some (eepro100) support the new interface just + # enough that they can report success but not actually do anything. Sweet! + # + my $ethtool; + if (-e "/sbin/ethtool") { + $ethtool = "/sbin/ethtool"; + } elsif (-e "/usr/sbin/ethtool") { + $ethtool = "/usr/sbin/ethtool"; + } + if (defined($ethtool)) { + # this seems to work for returning an error on eepro100 + $uplines = + "if $ethtool $iface >/dev/null 2>&1; then\n " . + " $ethtool -s $iface autoneg off speed $speed duplex $duplex\n " . + "else\n " . + " /sbin/mii-tool --force=$media $iface\n " . + "fi\n "; + } else { + $uplines = "/sbin/mii-tool --force=$media $iface\n "; + } + + if ($inet ne "") { + $uplines .= sprintf($IFCONFIG, $iface, $inet, $mask); + $downlines = "$IFCONFIGBIN $iface down"; + } + + return ($uplines, $downlines); +} + +# +# Specialized function for configing locally hacked veth devices. +# +sub os_ifconfig_veth($$$$$;$$$) +{ + return ""; +} + +# +# Generate and return an string that is approriate for putting +# into /etc/hosts. +# +sub os_etchosts_line($$$) +{ + my ($name, $ip, $aliases) = @_; + + return sprintf("%s\t%s %s", $ip, $name, $aliases); +} + +# +# Add a new group +# +sub os_groupadd($$) +{ + my($group, $gid) = @_; + + return system("$GROUPADD -g $gid $group"); +} + +# +# Delete an old group +# +sub os_groupdel($) +{ + my($group) = @_; + + return system("$GROUPDEL $group"); +} + +# +# Remove a user account. +# +sub os_userdel($) +{ + my($login) = @_; + + return system("$USERDEL $login"); +} + +# +# Modify user group membership. +# +sub os_usermod($$$$$$) +{ + my($login, $gid, $glist, $pswd, $root, $shell) = @_; + + if ($root) { + $glist = join(',', split(/,/, $glist), "root"); + } + if ($glist ne "") { + $glist = "-G $glist"; + } + # Map the shell into a full path. + $shell = MapShell($shell); + + return system("$USERMOD -s $shell -g $gid $glist -p '$pswd' $login"); +} + +# +# Add a user. +# +sub os_useradd($$$$$$$$$) +{ + my($login, $uid, $gid, $pswd, $glist, $homedir, $gcos, $root, $shell) = @_; + + if ($root) { + $glist = join(',', split(/,/, $glist), "root"); + } + if ($glist ne "") { + $glist = "-G $glist"; + } + # Map the shell into a full path. + $shell = MapShell($shell); + + if (system("$USERADD -M -u $uid -g $gid $glist -p '$pswd' ". + "-d $homedir -s $shell -c \"$gcos\" $login") != 0) { + warn "*** WARNING: $USERADD $login error.\n"; + return -1; + } + return 0; +} + +# +# Remove a homedir. Might someday archive and ship back. +# +sub os_homedirdel($$) +{ + return 0; +} + +# +# Create a directory including all intermediate directories. +# +sub os_mkdir($$) +{ + my ($dir, $mode) = @_; + + if (system("$MKDIR -p -m $mode $dir")) { + return 0; + } + return 1; +} + +# +# OS Dependent configuration. +# +sub os_setup() +{ + return 0; +} + +# +# OS dependent, routing-related commands +# +sub os_routing_enable_forward() +{ + my $cmd; + + $cmd = "sysctl -w net.ipv4.conf.all.forwarding=1"; + return $cmd; +} + +sub os_routing_enable_gated($) +{ + my ($conffile) = @_; + my $cmd; + + # + # XXX hack to avoid gated dying with TCP/616 already in use. + # + # Apparently the port is used by something contacting ops's + # portmapper (i.e., NFS mounts) and probably only happens when + # there are a bazillion NFS mounts (i.e., an experiment in the + # testbed project). + # + $cmd = "for try in 1 2 3 4 5 6; do\n"; + $cmd .= "\tif `cat /proc/net/tcp | ". + "grep -E -e '[0-9A-Z]{8}:0268 ' >/dev/null`; then\n"; + $cmd .= "\t\techo 'gated GII port in use, sleeping...';\n"; + $cmd .= "\t\tsleep 10;\n"; + $cmd .= "\telse\n"; + $cmd .= "\t\tbreak;\n"; + $cmd .= "\tfi\n"; + $cmd .= " done\n"; + $cmd .= " $GATED -f $conffile"; + return $cmd; +} + +sub os_routing_add_manual($$$$$;$) +{ + my ($routetype, $destip, $destmask, $gate, $cost, $rtabid) = @_; + my $cmd; + + if ($routetype eq "host") { + $cmd = "$ROUTE add -host $destip gw $gate"; + } elsif ($routetype eq "net") { + $cmd = "$ROUTE add -net $destip netmask $destmask gw $gate"; + } elsif ($routetype eq "default") { + $cmd = "$ROUTE add default gw $gate"; + } else { + warn "*** WARNING: bad routing entry type: $routetype\n"; + $cmd = ""; + } + + return $cmd; +} + +sub os_routing_del_manual($$$$$;$) +{ + my ($routetype, $destip, $destmask, $gate, $cost, $rtabid) = @_; + my $cmd; + + if ($routetype eq "host") { + $cmd = "$ROUTE delete -host $destip"; + } elsif ($routetype eq "net") { + $cmd = "$ROUTE delete -net $destip netmask $destmask gw $gate"; + } elsif ($routetype eq "default") { + $cmd = "$ROUTE delete default"; + } else { + warn "*** WARNING: bad routing entry type: $routetype\n"; + $cmd = ""; + } + + return $cmd; +} + +# Map a shell name to a full path using /etc/shells +sub MapShell($) +{ + my ($shell) = @_; + + if ($shell eq "") { + return $DEFSHELL; + } + + my $fullpath = `grep '/${shell}\$' $SHELLS`; + + if ($?) { + return $DEFSHELL; + } + + # Sanity Check + if ($fullpath =~ /^([-\w\/]*)$/) { + $fullpath = $1; + } + else { + $fullpath = $DEFSHELL; + } + return $fullpath; +} + +# Extract the local mount point from a remote mount path. +sub os_mountlocal($) +{ + my ($remote) = @_; + my $local = $remote; + $local =~ s|^.*:||; # Remove server prefix. + $local =~ s|^/q/proj/|/proj/|; # Remove /q prefix from /proj. + return $local; +} + +sub os_getnfsmounts($) +{ + my ($rptr) = @_; + my %mounted = (); + + # + # Grab the output of the mount command and parse. ("net use" on Windows.) + # + if (! open(MOUNT, "$NET use|")) { + print "os_getnfsmounts: Cannot run net use command\n"; + return -1; + } + while (<MOUNT>) { + # We get lines like: + # P: \\fs.emulab.net\q\proj\testbed NFS Network + # When the remote string is too long, "NFS Network" is on the next line. + if ($_ =~ m|^ +(\w:) +([-\w\.\\]+)|) { + # Bash the remote UNC path into a NFS path like fs:/q/proj/testbed . + my $driveletter = $1; + my $rpath = $2; + $rpath =~ s|^\\\\([-\w\.]+)|$1:|; # \\host -> host: + $rpath =~ s|\\|/|g; # Backslashes to forward. + # Key is the remote NFS path, value is the CygWin local path. + $mounted{$rpath} = os_mountlocal($rpath); + } + } + close(MOUNT); + %$rptr = %mounted; + return 0; +} + +sub os_getnfsmountpoints($) +{ + my ($rptr) = @_; + my %mounted = (); + + # + # Grab the output of the mount command and parse. ("net use" on Windows.) + # + if (! open(MOUNT, "$NET use|")) { + print "os_getnfsmounts: Cannot run net use command\n"; + return -1; + } + while (<MOUNT>) { + # We get lines like: + # P: \\fs.emulab.net\q\proj\testbed NFS Network + # When the remote string is too long, "NFS Network" is on the next line. + ##print; + if ($_ =~ m|^ +(\w:) +([-\w\.\\]+)|) { + # Bash the remote UNC path into a NFS path like fs:/q/proj/testbed . + my $driveletter = $1; + my $rpath = $2; + ##print "driveletter '$driveletter', rpath '$rpath'\n"; + $rpath =~ s|^\\\\([-\w\.]+)|$1:|; # \\host -> host: + $rpath =~ s|\\|/|g; # Backslashes to forward. + ##print "driveletter '$driveletter', rpath '$rpath'\n"; + # Key is CygWin local path, value is drive letter and remote NFS path. + my $local = os_mountlocal($rpath); + ##print "local '$local'\n"; + $mounted{$local} = [$rpath, $driveletter]; + } + } + close(MOUNT); + %$rptr = %mounted; + return 0; +} + +# Execute a noisy bash command, throwing away the output unless we ask for it. +sub os_noisycmd($$) +{ + my ($cmd, $verbose) = @_; + my $bashcmd = "$BASH -c '$cmd'" . ($verbose ? "" : " > /dev/null"); + my $ret = system($bashcmd); + ##print "os_noisycmd cmd '$cmd', ret $ret\n"; + return $ret +} + +sub os_fwconfig_line($@) +{ + my ($fwinfo, @fwrules) = @_; + my ($upline, $downline); + my $errstr = "*** WARNING: Linux firewall not implemented\n"; + + + warn $errstr; + $upline = "echo $errstr; exit 1"; + $downline = "echo $errstr; exit 1"; + + return ($upline, $downline); +} + +sub os_fwrouteconfig_line($$$) +{ + my ($orouter, $fwrouter, $routestr) = @_; + my ($upline, $downline); + + # + # XXX assume the original default route should be used to reach servers. + # + # For setting up the firewall, this means we create explicit routes for + # each host via the original default route. + # + # For tearing down the firewall, we just remove the explicit routes + # and let them fall back on the now re-established original default route. + # + $upline = "for vir in $routestr; do\n"; + $upline .= " $ROUTE delete \$vir >/dev/null 2>&1\n"; + $upline .= " $ROUTE add -host \$vir gw $orouter || {\n"; + $upline .= " echo \"Could not establish route for \$vir\"\n"; + $upline .= " exit 1\n"; + $upline .= " }\n"; + $upline .= " done"; + + $downline = "for vir in $routestr; do\n"; + $downline .= " $ROUTE delete \$vir >/dev/null 2>&1\n"; + $downline .= " done"; + + return ($upline, $downline); +} + +1; diff --git a/tmcd/cygwinxp/profile b/tmcd/cygwinxp/profile new file mode 100755 index 0000000000..da89fdb4af --- /dev/null +++ b/tmcd/cygwinxp/profile @@ -0,0 +1,77 @@ +# Some resources... + +# Customizing Your Shell: http://www.dsl.org/cookbook/cookbook_5.html#SEC69 +# Consistent BackSpace and Delete Configuration: +# http://www.ibb.net/~anne/keyboard.html + +# Setup some default paths. Note that this order will allow user installed +# software to override 'system' software + +# If you wish to change the path on a user by user basis, it is recommended you +# edit ~/.bashrc + +# If you wish to change the path for all users, it is recommended you edit +# /etc/bash.bashrc + +export PATH="/usr/local/bin:/usr/bin:/bin:$PATH" + +# Set the user id +export USER="`id -un`" + +# Here is how HOME is set, in order of priority, when starting from Windows +# 1) From existing HOME in the Windows environment, translated to a Posix path +# 2) from /etc/passwd, if there is an entry with a non empty directory field +# 3) from HOMEDRIVE/HOMEPATH +# 4) / (root) + +# Use a local dir under sshd for now. +if [ ! -d "$HOME" ]; then + HOME=/home/$USER +fi +# If the home directory doesn't exist, create it. +if [ ]; then + mkdir -p "$HOME" + # copy skeleton files + cd /etc/skel + for f in `/bin/find . -type f`; do + fDest=`echo $f | sed -e 's/^\.//g'` + if [ ! -e "$HOME$fDest" -a ! -L "$HOME$fDest" ]; then + cp "$f" "$HOME/$fDest" + fi + done +fi + +# run all of the profile.d scripts +for i in /etc/profile.d/*.sh ; do + if [ -f $i ]; then + . $i + fi +done + +# default to unix make mode +export MAKE_MODE=unix + +# it is recommended that cvs uses ssh for it's remote shell environment +export CVS_RSH=/bin/ssh + +# Patches to Cygwin always appreciated ;) +# export CVSROOT=:pserver:anoncvs@sources.redhat.com:/cvs/src + +# Set a HOSTNAME variable +export HOSTNAME=`hostname` + +# set a default prompt of: user@host current_directory +export PS1='\[\033]0;\w\007 +\033[32m\]\u@\h \[\033[33m\w\033[0m\] +$ ' + +# uncomment to use the terminal colours set in DIR_COLOR +# eval `dircolors -b /etc/DIR_COLOR` + +# default to removing the write permission for group and other +# (files normally created with mode 777 become 755; files created with +# mode 666 become 644) +umask 022 + +# make sure we start in home +cd "$HOME" diff --git a/tmcd/cygwinxp/rc.cygwinxp b/tmcd/cygwinxp/rc.cygwinxp new file mode 100755 index 0000000000..b96e477ee8 --- /dev/null +++ b/tmcd/cygwinxp/rc.cygwinxp @@ -0,0 +1,19 @@ +#!/bin/bash +# +# EMULAB-COPYRIGHT +# Copyright (c) 2004 University of Utah and the Flux Group. +# All rights reserved. +# +# CygWin startup. + +# Make sure the node name is right. +nodeid=`/usr/local/etc/emulab/tmcc.bin nodeid` +hostname=`/bin/hostname` +if [ $nodeid == $hostname ]; then + echo "Host name '$hostname' matches nodeid '$nodeid'." > /tmp/wsname +else + echo "Host name '$hostname' and nodeid '$nodeid' differ." > /tmp/wsname + + # Change hostname and computername, rename My Computer, reboot on success. + /usr/local/etc/emulab/WSName /N:$nodeid /REBOOT /MCN +fi diff --git a/tmcd/cygwinxp/rc.cygwinxp-user b/tmcd/cygwinxp/rc.cygwinxp-user new file mode 100644 index 0000000000..66508738c7 --- /dev/null +++ b/tmcd/cygwinxp/rc.cygwinxp-user @@ -0,0 +1,40 @@ +#!/bin/bash +# +# EMULAB-COPYRIGHT +# Copyright (c) 2004 University of Utah and the Flux Group. +# All rights reserved. +# +# CygWin user setup for each login. + +PATH=/usr/local/etc/emulab:$PATH +set -x + +# Mounts are local to the Win32 login session context. +if [ -e /cygdrive/s ]; then /cygdrive/c/SFU/common/umount S: > /dev/null; fi +emount fs.emulab.net:/share /share + +if [ -e /cygdrive/p ]; then /cygdrive/c/SFU/common/umount P: > /dev/null ; fi +proj=`tmcc.bin status | sed 's|ALLOCATED=\([^/]*\)/.*|\1|'` +emount fs.emulab.net:/q/proj/$proj /proj/$proj + +if [ -e /cygdrive/h ]; then /cygdrive/c/SFU/common/umount H: > /dev/null ; fi +creator=`tmcc.bin creator | sed 's|.*CREATOR=\([^ ]*\).*|\1|'` +emount fs.emulab.net:/users/$creator /users/$creator + +if [ -e /cygdrive/i ]; then /cygdrive/c/SFU/common/umount I: > /dev/null ; fi +swapper=`tmcc.bin creator | sed 's|.*SWAPPER=\([^ ]*\).*|\1|'` +if [ $swapper != $creator ]; then + emount fs.emulab.net:/users/$swapper /users/$swapper +fi + +# Make sure the user's homedir is mounted if neither creator nor swapper. +if [ -e /cygdrive/j ]; then /cygdrive/c/SFU/common/umount J: > /dev/null ; fi +user=`id -un` +if [[ $user != $creator && $user != $swapper && $user != root ]]; then + emount -d J: fs.emulab.net:/users/$user /users/$user +fi + +set +x +echo "Hit <Enter> to dismiss." +sed 1q + -- GitLab