Finish afscell implementation work
authorToby Blake <toby@inf.ed.ac.uk>
Thu, 23 Jul 2009 19:18:28 +0000 (20:18 +0100)
committerDerrick Brashear <shadow@dementia.org>
Fri, 24 Jul 2009 01:48:55 +0000 (18:48 -0700)
This patch completes the implementation of an install time prompeter
for information about the local AFS cell, which is then used to populate
the ThisCell file. It removes the need for manual editing of
configuration files as part of the installation.

(Build system modified by Simon Wilkinson from Toby's original patch)

Reviewed-on: http://gerrit.openafs.org/http://gerrit.openafs.org/201
Tested-by: Derrick Brashear <shadow@dementia.org>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

18 files changed:
src/packaging/MacOS/InstallationCheck.10
src/packaging/MacOS/InstallationCheck.8
src/packaging/MacOS/InstallationCheck.9
src/packaging/MacOS/OpenAFS.post_install
src/packaging/MacOS/ReadMe.rtf.10
src/packaging/MacOS/ReadMe.rtf.8
src/packaging/MacOS/ReadMe.rtf.9
src/packaging/MacOS/buildpkg.sh.in
src/platform/DARWIN/Makefile.in
src/platform/DARWIN/afscell/.gitignore [new file with mode: 0644]
src/platform/DARWIN/afscell/English.lproj/Localizable.strings
src/platform/DARWIN/afscell/English.lproj/afscell.nib/classes.nib
src/platform/DARWIN/afscell/English.lproj/afscell.nib/info.nib
src/platform/DARWIN/afscell/English.lproj/afscell.nib/keyedobjects.nib
src/platform/DARWIN/afscell/InstallerSections.plist
src/platform/DARWIN/afscell/afscell.xcodeproj/project.pbxproj
src/platform/DARWIN/afscell/afscellPane.h
src/platform/DARWIN/afscell/afscellPane.m

index 71e1782..b4774bf 100644 (file)
@@ -6,5 +6,17 @@ echo "InstallationCheck: not ok"
        exit 112
 fi
 
+# check for temporary versions of ThisCell and CellAlias
+# and move them aside
+tmpthiscell=/private/tmp/org.OpenAFS.Install.ThisCell.$USER
+tmpcellalias=/private/tmp/org.OpenAFS.Install.CellAlias.$USER
+date=`date +%Y%m%d%H%M`
+if [ -e $tmpthiscell ]; then
+    mv -f $tmpthiscell $tmpthiscell.$date
+fi
+if [ -e $tmpcellalias ]; then
+    mv -f $tmpcellalias $tmpcellalias.$date
+fi
+
 echo "InstallationCheck: ok"
 exit 0
index d905d15..1975ef7 100644 (file)
@@ -6,5 +6,17 @@ echo "InstallationCheck: not ok"
        exit 112
 fi
 
+# check for temporary versions of ThisCell and CellAlias
+# and move them aside
+tmpthiscell=/private/tmp/org.OpenAFS.Install.ThisCell.$USER
+tmpcellalias=/private/tmp/org.OpenAFS.Install.CellAlias.$USER
+date=`date +%Y%m%d%H%M`
+if [ -e $tmpthiscell ]; then
+    mv -f $tmpthiscell $tmpthiscell.$date
+fi
+if [ -e $tmpcellalias ]; then
+    mv -f $tmpcellalias $tmpcellalias.$date
+fi
+
 echo "InstallationCheck: ok"
 exit 0
index 9061222..05e2592 100644 (file)
@@ -6,5 +6,17 @@ echo "InstallationCheck: not ok"
        exit 112
 fi
 
+# check for temporary versions of ThisCell and CellAlias
+# and move them aside
+tmpthiscell=/private/tmp/org.OpenAFS.Install.ThisCell.$USER
+tmpcellalias=/private/tmp/org.OpenAFS.Install.CellAlias.$USER
+date=`date +%Y%m%d%H%M`
+if [ -e $tmpthiscell ]; then
+    mv -f $tmpthiscell $tmpthiscell.$date
+fi
+if [ -e $tmpcellalias ]; then
+    mv -f $tmpcellalias $tmpcellalias.$date
+fi
+
 echo "InstallationCheck: ok"
 exit 0
index 182b393..9483b9d 100644 (file)
@@ -32,6 +32,19 @@ if [ `grep /Network/afs cacheinfo` ]; then
     mv cacheinfo.new cacheinfo
 fi
 
+# if the installer plugin generated ThisCell and/or CellAlias
+# files, copy them in here
+tmpthiscell=/private/tmp/org.OpenAFS.Install.ThisCell.$USER
+tmpcellalias=/private/tmp/org.OpenAFS.Install.CellAlias.$USER
+if [ -f $tmpthiscell ]; then
+    cp $tmpthiscell ThisCell
+    rm -f $tmpthiscell
+fi
+if [ -f $tmpcellalias ]; then
+    cp $tmpcellalias CellAlias
+    rm -f $tmpcellalias
+fi
+
 if [ ! -f ThisCell -a -f ThisCell.sample ]; then
    cp ThisCell.sample ThisCell
 fi
index c6b346b..e13ca9c 100644 (file)
@@ -4,9 +4,7 @@
 \margl1440\margr1440\vieww9000\viewh9000\viewkind0
 \pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
 
-\f0\fs20 \cf0 This release of OpenAFS is targeted at MacOS 10.6. (Snow Leopard)
-\
-Select a client cell name by editing /var/db/openafs/etc/ThisCell\
+\f0\fs24 \cf0 This release of OpenAFS is targeted at MacOS 10.6. (Snow Leopard)\
 \
 The included afssettings program is distributed under the Apple Public Source License, version 2.0. See http://www.opensource.apple.com/apsl/2.0.txt or the included file 2.0.txt.\
 \
index ada1c7d..c9904f0 100644 (file)
@@ -4,9 +4,7 @@
 \margl1440\margr1440\vieww9000\viewh9000\viewkind0
 \pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
 
-\f0\fs20 \cf0 This release of OpenAFS is targeted at MacOS 10.4. (Tiger)
-\
-Select a client cell name by editing /var/db/openafs/etc/ThisCell\
+\f0\fs24 \cf0 This release of OpenAFS is targeted at MacOS 10.4. (Tiger)\
 \
 The included afssettings program is distributed under the Apple Public Source License, version 2.0. See http://www.opensource.apple.com/apsl/2.0.txt or the included file 2.0.txt.\
 \
index dfba64d..8e606d6 100644 (file)
@@ -4,9 +4,7 @@
 \margl1440\margr1440\vieww9000\viewh9000\viewkind0
 \pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
 
-\f0\fs20 \cf0 This release of OpenAFS is targeted at MacOS 10.5. (Leopard)
-\
-Select a client cell name by editing /var/db/openafs/etc/ThisCell\
+\f0\fs24 \cf0 This release of OpenAFS is targeted at MacOS 10.5. (Leopard)\
 \
 The included afssettings program is distributed under the Apple Public Source License, version 2.0. See http://www.opensource.apple.com/apsl/2.0.txt or the included file 2.0.txt.\
 \
index e75ccb6..0dc9ac3 100644 (file)
@@ -229,6 +229,23 @@ if [ $secondpass = yes ]; then
     fi
 
     rm -rf $PKGROOT $PKGRES
+
+    # here we want to build installer plugin and install
+    # for Tiger and later only
+    if [ $majorvers -ge 8 ]; then
+       AFSCELLBUNDLE=$BINDEST/installer/afscell.bundle
+       cd $CURDIR
+       if [ -d $AFSCELLBUNDLE -a -f $BINDEST/installer/InstallerSections.plist ]; then
+           mkdir -p $CURDIR/OpenAFS.pkg/Contents/Plugins
+           cp -R $AFSCELLBUNDLE $CURDIR/OpenAFS.pkg/Contents/Plugins
+           cp $BINDEST/installer/InstallerSections.plist $CURDIR/OpenAFS.pkg/Contents/Plugins
+       else
+           echo "afscell.bundle not built successfully"
+           echo "... or InstallerSections.plist file not found"
+           exit 1
+       fi
+    fi
+
     mkdir $CURDIR/dmg
     mv $CURDIR/OpenAFS.pkg $CURDIR/dmg
     rm -rf $CURDIR/OpenAFS-@VERSION@-$RELNAME.dmg
index edfbddb..c42aa41 100644 (file)
@@ -11,14 +11,18 @@ INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
 INSTALL_SCRIPT = @INSTALL_SCRIPT@
-include ../../config/Makefile.version
 
-all: OpenAFS.prefPane afssettings
+.PHONY: all afscell
+
+all: OpenAFS.prefPane afssettings afscell
 
 OpenAFS.prefPane:
        xcodebuild -project AFSPreference/OpenAFS.xcodeproj
        mv AFSPreference/build/Release/OpenAFS.prefPane OpenAFS.prefPane
 
+afscell:
+       cd afscell && xcodebuild
+
 afssettings: afssettings.m 
        ${CC} ${CFLAGS} -o afssettings afssettings.m -framework Foundation
 
@@ -26,7 +30,9 @@ install: \
        ${DESTDIR}${sbindir}/afssettings
 
 dest: \
-       ${DEST}/etc/afssettings
+       ${DEST}/etc/afssettings \
+       ${DEST}/installer/afscell.bundle \
+       ${DEST}/installer/InstallerSections.plist
 
 ${DESTDIR}${sbindir}/afssettings: afssettings
        ${INSTALL} $? $@
@@ -34,7 +40,16 @@ ${DESTDIR}${sbindir}/afssettings: afssettings
 ${DEST}/etc/afssettings: afssettings
        ${INSTALL} $? $@
 
+${DEST}/installer/afscell.bundle: afscell/build/Release/afscell.bundle
+       mkdir -p ${DEST}/installer
+       rm -rf ${DEST}/installer/afscell.bundle
+       cp -R $? $@
+
+${DEST}/installer/InstallerSections.plist: afscell/InstallerSections.plist
+       ${INSTALL} $? $@
+
 clean:
        $(RM) -rf OpenAFS.prefPane
        $(RM) -rf AFSPreference/build
-       $(RM) -f *.o core afssettings AFS_component_version_number.c 
+       $(RM) -f *.o core afssettings AFS_component_version_number.c
+       @cd afscell && xcodebuild clean
diff --git a/src/platform/DARWIN/afscell/.gitignore b/src/platform/DARWIN/afscell/.gitignore
new file mode 100644 (file)
index 0000000..619203d
--- /dev/null
@@ -0,0 +1,5 @@
+# After changing this file, please run
+#     git ls-files -i --exclude-standard
+# to check that you haven't inadvertently ignored any tracked files.
+
+/build
index 34935d4..d9ce60d 100644 (file)
Binary files a/src/platform/DARWIN/afscell/English.lproj/Localizable.strings and b/src/platform/DARWIN/afscell/English.lproj/Localizable.strings differ
index 339f1df..010d239 100644 (file)
@@ -1,31 +1,70 @@
-{
-    IBClasses = (
-        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
-        {
-            CLASS = InstallerPane; 
-            LANGUAGE = ObjC; 
-            OUTLETS = {
-                contentView = NSView; 
-                firstKeyView = NSView; 
-                initialKeyView = NSView; 
-                lastKeyView = NSView; 
-                nextPane = InstallerPane; 
-                parentSection = id; 
-            }; 
-            SUPERCLASS = NSObject; 
-        }, 
-        {
-            CLASS = InstallerSection; 
-            LANGUAGE = ObjC; 
-            OUTLETS = {firstPane = InstallerPane; }; 
-            SUPERCLASS = NSObject; 
-        }, 
-        {
-            CLASS = afscellPane; 
-            LANGUAGE = ObjC; 
-            OUTLETS = {CellAlias = id; ThisCell = id; }; 
-            SUPERCLASS = InstallerPane; 
-        }
-    ); 
-    IBVersion = 1; 
-}
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>IBClasses</key>
+       <array>
+               <dict>
+                       <key>CLASS</key>
+                       <string>afscellPane</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>OUTLETS</key>
+                       <dict>
+                               <key>CellAlias</key>
+                               <string>NSTextField</string>
+                               <key>ThisCell</key>
+                               <string>NSTextField</string>
+                       </dict>
+                       <key>SUPERCLASS</key>
+                       <string>InstallerPane</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>InstallerSection</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>OUTLETS</key>
+                       <dict>
+                               <key>firstPane</key>
+                               <string>InstallerPane</string>
+                       </dict>
+                       <key>SUPERCLASS</key>
+                       <string>NSObject</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>InstallerPane</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>OUTLETS</key>
+                       <dict>
+                               <key>contentView</key>
+                               <string>NSView</string>
+                               <key>firstKeyView</key>
+                               <string>NSView</string>
+                               <key>initialKeyView</key>
+                               <string>NSView</string>
+                               <key>lastKeyView</key>
+                               <string>NSView</string>
+                               <key>nextPane</key>
+                               <string>InstallerPane</string>
+                               <key>parentSection</key>
+                               <string>id</string>
+                       </dict>
+                       <key>SUPERCLASS</key>
+                       <string>NSObject</string>
+               </dict>
+               <dict>
+                       <key>CLASS</key>
+                       <string>FirstResponder</string>
+                       <key>LANGUAGE</key>
+                       <string>ObjC</string>
+                       <key>SUPERCLASS</key>
+                       <string>NSObject</string>
+               </dict>
+       </array>
+       <key>IBVersion</key>
+       <string>1</string>
+</dict>
+</plist>
index 9a6acbf..f96e1a8 100644 (file)
@@ -1,23 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-       <key>IBDocumentLocation</key>
-       <string>51 74 356 240 0 0 1280 1002 </string>
-       <key>IBEditorPositions</key>
-       <dict>
-               <key>8</key>
-               <string>421 502 438 372 0 0 1280 1002 </string>
-       </dict>
        <key>IBFramework Version</key>
-       <string>446.1</string>
+       <string>629</string>
+       <key>IBLastKnownRelativeProjectPath</key>
+       <string>../../afscell.xcodeproj</string>
+       <key>IBOldestOS</key>
+       <integer>5</integer>
        <key>IBOpenObjects</key>
        <array>
                <integer>8</integer>
        </array>
        <key>IBSystem Version</key>
-       <string>8R2218</string>
-       <key>IBUsesTextArchiving</key>
-       <true/>
+       <string>9C31</string>
+       <key>targetFramework</key>
+       <string>IBCocoaFramework</string>
 </dict>
 </plist>
index df1e573..ff42d35 100644 (file)
Binary files a/src/platform/DARWIN/afscell/English.lproj/afscell.nib/keyedobjects.nib and b/src/platform/DARWIN/afscell/English.lproj/afscell.nib/keyedobjects.nib differ
index e9028b9..fc3dc3e 100644 (file)
@@ -10,7 +10,8 @@
                <string>afscell.bundle</string>
                <string>Target</string>
                <string>PackageSelection</string>
-               <string>Install</string>                
+               <string>Install</string>
+               <string>Summary</string>        
        </array>
 </dict>
 </plist>
index 33753de..d8ac099 100644 (file)
@@ -3,7 +3,7 @@
        archiveVersion = 1;
        classes = {
        };
-       objectVersion = 42;
+       objectVersion = 44;
        objects = {
 
 /* Begin PBXBuildFile section */
                1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
                32DBCF630370AF2F00C91783 /* afscell_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = afscell_Prefix.pch; sourceTree = "<group>"; };
                8D5B49B6048680CD000E48DA /* afscell.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = afscell.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
-               8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
+               8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
                B40F7FFB06739E1B0053A16B /* InstallerPlugins.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InstallerPlugins.framework; path = /System/Library/Frameworks/InstallerPlugins.framework; sourceTree = "<absolute>"; };
                B40F802806739F480053A16B /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/afscell.nib; sourceTree = "<group>"; };
                B44C200806739AE500D31AA1 /* afscellPane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = afscellPane.h; sourceTree = "<group>"; };
                B44C200906739AE500D31AA1 /* afscellPane.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = afscellPane.m; sourceTree = "<group>"; };
                B47CF354067B4E030066DBF6 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = "<group>"; };
-               B4A6B2A60673D523003CD9B2 /* InstallerSections.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = InstallerSections.plist; sourceTree = "<group>"; };
+               B4A6B2A60673D523003CD9B2 /* InstallerSections.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = InstallerSections.plist; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                089C1669FE841209C02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = B44174EA08BA33C40065BEDE /* Build configuration list for PBXProject "afscell" */;
+                       compatibilityVersion = "Xcode 3.0";
                        hasScannedForEncodings = 1;
                        mainGroup = 089C166AFE841209C02AAC07 /* InstallerPlugin */;
                        projectDirPath = "";
+                       projectRoot = "";
                        targets = (
                                8D5B49AC048680CD000E48DA /* afscell */,
                        );
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PREBINDING = NO;
-                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                               SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
                        };
                        name = Debug;
                };
                B44174EC08BA33C40065BEDE /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               GCC_ENABLE_OBJC_GC = supported;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                PREBINDING = NO;
-                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                               SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
                        };
                        name = Release;
                };
index 5c4e985..9688358 100644 (file)
@@ -9,7 +9,6 @@
 #import <Cocoa/Cocoa.h>
 #import <InstallerPlugins/InstallerPlugins.h>
 
-
 @interface afscellPane : InstallerPane {
 
        IBOutlet NSTextField * ThisCell;
index f8ac9b2..1b1ec29 100644 (file)
 //  afscell
 //
 //  Created by David Botsch on 10/23/07.
-//  Copyright (c) 2007 __MyCompanyName__. All rights reserved.
+//  Further developed by Toby Blake, April-May 2008
 //
 
 #import "afscellPane.h"
 
-
 @implementation afscellPane
 
+#pragma mark string constants
+NSString *fileReadThisCell=@"/private/var/db/openafs/etc/ThisCell";
+NSString *fileReadCellAlias=@"/private/var/db/openafs/etc/CellAlias";
+NSString *fileWriteThisCell=@"/private/tmp/org.OpenAFS.Install.ThisCell";
+NSString *fileWriteCellAlias=@"/private/tmp/org.OpenAFS.Install.CellAlias";
+
+#pragma mark private methods
+/* check line of CellAlias provided for Cell name, if matches, returns alias in third parameter */
+- (BOOL)_cellInCellAliasLine:(NSString *)line cellName:(NSString *)cell intoAlias:(NSString **)alias
+{
+       NSCharacterSet *alphaNum = [NSCharacterSet alphanumericCharacterSet];
+       NSScanner *cellScanner = [NSScanner scannerWithString:line];
+       if (![cellScanner scanUpToString:cell intoString:nil])
+       {
+               [cellScanner scanString:cell intoString:nil];
+               /* need to make sure cell name is followed by whitespace */
+               if (![cellScanner scanUpToCharactersFromSet:alphaNum intoString:nil])
+               {
+                       /* we have a match */
+                       /* get rest of string */
+                       [cellScanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:alias];
+                       return YES;
+               }       
+       }
+       return NO;
+}
+
+/* writes supplied line (plus newline) to string */
+- (void)_appendCellAliasLine:(NSString *)line toString:(NSMutableString *)outString
+{
+       [outString appendString:line];
+       [outString appendFormat:@"\n"];
+}
+
+/* writes supplied cell and alias, separated by space (plus newline at end) to string */
+- (void)_appendNewCellAliasLine:(NSString *)cell aliasName:(NSString *)alias toString:(NSMutableString *)outString
+{
+       [outString appendString:cell];
+       [outString appendFormat:@" "];
+       [outString appendString:alias];
+       [outString appendFormat:@"\n"];
+}
+
+/* displays (slightly) customisable alert */
+/* we don't use this method any more, but I'll leave it in just in case */
+- (BOOL) _continueAlert:(NSString *)message cancel:(BOOL)cancelButton
+{
+       BOOL returnValue = NO;
+       NSAlert *alert = [[NSAlert alloc] init];
+       [alert addButtonWithTitle:@"OK"];
+       (cancelButton) && [alert addButtonWithTitle:@"Cancel"];
+       [alert setMessageText:message];
+       [alert setAlertStyle:NSWarningAlertStyle];
+       
+       if ([alert runModal] == NSAlertFirstButtonReturn)
+       {
+               returnValue= YES;
+       }
+       [alert release];
+       return returnValue;
+}
+
+/* displays (slightly) customisable alert as a more attractive panel than _continueAlert above*/
+- (BOOL) _continueAlertPanel:(NSString *)message titleText:(NSString *)title firstButtonText:(NSString *)button1 secondButtonText:(NSString *)button2 
+{
+       if (NSRunInformationalAlertPanel(title, message, button1, button2, nil)
+               == NSAlertDefaultReturn)
+       {
+               return YES;
+       }
+       return NO;
+}
+
+- (BOOL) _validateStringWord:(NSString *)aString
+{
+       /* basic string validation to check it's got something in it, doesn't have whitespace or newline */
+       if (aString == nil || [aString length] == 0)
+       {
+               return NO;
+       }
+
+       if (([aString rangeOfString:@"\n"].location != NSNotFound) ||
+               ([aString rangeOfString:@"\t"].location != NSNotFound) ||
+               ([aString rangeOfString:@" "].location != NSNotFound))
+       {
+               return NO;
+       }
+       return YES;
+}
+
+- (BOOL) _validateCellString:(NSString *)cellString
+{
+       if (![self _validateStringWord:cellString])
+       {
+               return NO;
+       }
+
+       /* make sure it's in internet domain style, i.e. alphanum.alphanum */
+       NSCharacterSet *alphaNum = [NSCharacterSet alphanumericCharacterSet];
+       NSScanner *cellScanner = [NSScanner scannerWithString:cellString];
+       
+       /* first 'word' */
+       if (![cellScanner scanCharactersFromSet:alphaNum intoString:nil])
+       {
+               return NO;
+       }
+
+       /* anything that follows must be iteration of '.word' */
+       while (![cellScanner isAtEnd])
+       {
+               if (![cellScanner scanString:@"." intoString:nil])
+               {
+                       return NO;
+               }
+               if (![cellScanner scanCharactersFromSet:alphaNum intoString:nil])
+               {
+                       return NO;
+               }               
+       }
+       
+       return YES;
+}
+
+- (BOOL) _validateAliasString:(NSString *)aliasString
+{
+       if (![self _validateStringWord:aliasString])
+       {
+               return NO;
+       }
+
+       /* make sure it's alpha-numeric */
+       NSCharacterSet *alphaNum = [NSCharacterSet alphanumericCharacterSet];
+       NSScanner *aliasScanner = [NSScanner scannerWithString:aliasString];
+
+       if (![aliasScanner scanCharactersFromSet:alphaNum intoString:nil])
+       {
+               return NO;
+       }
+       /* if there's nothing but alpha-numeric, we should be at end */
+       if (![aliasScanner isAtEnd])
+       {
+               return NO;
+       }
+       
+       return YES;
+}
+
+#pragma mark InstallerPane overrides
 - (NSString *)title
 {
        return [[NSBundle bundleForClass:[self class]] localizedStringForKey:@"PaneTitle" value:nil table:nil];
 }
 
 
+/* called when user enters pane */
+- (BOOL)didEnterPane:(InstallerSectionDirection)dir
+{
+       /* get any existing values from ThisCell and CellAlias files */
+       NSString *readStrCellFile = [NSString stringWithContentsOfFile:fileReadThisCell encoding:NSASCIIStringEncoding error:nil];
+       NSString *readStrAliasFile = [NSString stringWithContentsOfFile:fileReadCellAlias encoding:NSASCIIStringEncoding error:nil];
+
+       /* drop out now if no ThisCell */
+       if (readStrCellFile == nil)
+       {
+               return YES;
+       }
+
+       NSString *cellString = @"";
+       NSString *aliasString = @"";
+
+       /* we only want the first line from ThisCell */
+       NSScanner *cellFileScanner = [NSScanner scannerWithString:readStrCellFile];
+
+       /* get value, removing any trailing whitespace */
+       [cellFileScanner scanUpToCharactersFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet] intoString:&cellString];
+
+       /* set Cell value in pane */
+       [ThisCell setStringValue:cellString];
+
+       /* drop out now if no CellAlias file */
+       if (readStrAliasFile == nil)
+       {
+               return YES;
+       }
+       
+       /* now find our local cell in the alias file */
+       NSScanner *lineScanner = [NSScanner scannerWithString:readStrAliasFile];
+       NSString *line;
+
+       /* get a line at a time, and check for Cell name */
+       while([lineScanner scanUpToString:@"\n" intoString:&line])
+       {
+               [self _cellInCellAliasLine:line cellName:cellString intoAlias:&aliasString];
+               [lineScanner scanString:@"\n" intoString:nil];
+       }
+
+       /* set Alias value in pane */
+       [CellAlias setStringValue:aliasString];
+
+       return YES;
+}
 
 /* called when user clicks "Continue" -- return value indicates if application should exit pane */
 - (BOOL)shouldExitPane:(InstallerSectionDirection)dir
 {
-       if(InstallerDirectionForward == dir) {
-               
+       if(InstallerDirectionForward == dir)
+       {
+               NSString * userName = NSUserName();
+
                /* Update ThisCell and CellAlias files with input */
-               NSString * WSCell = [ThisCell stringValue];
-               NSString * WSAlias = [CellAlias stringValue];
+               NSString * newStrCell = [ThisCell stringValue];
+               NSString * newStrAlias = [CellAlias stringValue];
+
+               if ([newStrCell length] == 0)
+               {
+                       return [self _continueAlertPanel:@"No local cell value specified.  Proceed with empty value?" titleText:@"No Local Cell" firstButtonText:@"Continue" secondButtonText:@"Cancel"];
+               }
                
+               /* do some validation on cell string */
+               if (![self _validateCellString:newStrCell])
+               {
+                       [self _continueAlertPanel:@"Invalid local cell name: value should be a complete Internet domain-style name (for example, \"abc.com\")" titleText:@"Invalid Cell Name" firstButtonText:@"OK" secondButtonText:nil];
+                       return NO;
+               }
                
-                                       
-                               BOOL wr1 = [WSCell writeToFile:@"/private/tmp/ThisCell" atomically:YES];
-                               BOOL wr2;
+               /* write value to ThisCell file */
                
-                               if ([WSAlias length] != 0) {
-                                       NSMutableString * aliasString = [[NSMutableString alloc] init];
-                                       [aliasString appendString:WSCell];
-                                       [aliasString appendFormat:@" "];
-                                       [aliasString appendString:WSAlias];
-                                       wr2 = [aliasString writeToFile:@"/private/tmp/CellAlias" atomically:YES];
-                               }
+               /* add username to file name */
+               NSMutableString * fileWriteThisCellUname = [NSMutableString stringWithCapacity:0];
+               [fileWriteThisCellUname appendString:fileWriteThisCell];
+               [fileWriteThisCellUname appendFormat:@"."];
+               [fileWriteThisCellUname appendString:userName];
+
+               NSMutableString * errorString = [NSMutableString stringWithCapacity:0];
+
+               NSMutableString * cellString = [NSMutableString stringWithCapacity:0];
+               [cellString appendString:newStrCell];
+               [cellString appendFormat:@"\n"];
+               if (![cellString writeToFile:fileWriteThisCellUname atomically:YES encoding:NSASCIIStringEncoding error:nil])
+               {
+                       [errorString setString:@"Could not write file: "];
+                       [errorString appendString:fileWriteThisCellUname];
+                       [errorString appendFormat:@"  Continue?"];
+                       if (![self _continueAlertPanel:errorString titleText:@"File Error" firstButtonText:@"Continue" secondButtonText:@"Cancel"])
+                       {
+                               return NO;
+                       }
+               }
+
+               if ([newStrAlias length] != 0)
+               {
+                       /* do some validation on alias string */
+                       if (![self _validateAliasString:newStrAlias])
+                       {
+                               [self _continueAlertPanel:@"Invalid alias: value should be alpha-numeric string" titleText:@"Invalid Alias" firstButtonText:@"OK" secondButtonText:nil];
+                               return NO;
+                       }
                
-                               NSMutableString * results = [[NSMutableString alloc] init];
-                               [results appendFormat:@"Write 1 is %d and write 2 is %d\n", wr1, wr2];
-                               [results writeToFile:@"/private/tmp/writefile" atomically:YES];
+                       BOOL processedAlias = NO;
+               
+                       /* read in alias file */
+                       NSString *readStrAliasFile = [NSString stringWithContentsOfFile:fileReadCellAlias encoding:NSASCIIStringEncoding error:nil];
+
+                       /* string to build up for writing out to file */
+                       NSMutableString * aliasString = [NSMutableString stringWithCapacity:0];
+
+                       if (readStrAliasFile != nil)
+                       {
+                               /* read in a line at a time */
+                               NSScanner *lineScanner = [NSScanner scannerWithString:readStrAliasFile];
+                               NSString *line;                                 
+                               NSString *alias = @"";
+
+                               while([lineScanner scanUpToString:@"\n" intoString:&line])
+                               {
+                                       /* check to see if we already have an alias for local cell */
+                                       if ([self _cellInCellAliasLine:line cellName:newStrCell intoAlias:&alias])
+                                       {
+                                               /* we have a match */
+                                               if ([alias isEqualToString:newStrAlias])
+                                               {
+                                                       /* write line as-is */
+                                                       [self _appendCellAliasLine:line toString:aliasString];
+                                               }
+                                               else
+                                               {
+                                                       /* write new cell-alias entry in place */
+                                                       [self _appendNewCellAliasLine:newStrCell aliasName:newStrAlias toString:aliasString];
+                                               }
+                                               processedAlias = YES;
+                                       }       
+                                       else
+                                       {
+                                               /* write line as-is */
+                                               [self _appendCellAliasLine:line toString:aliasString];
+                                       }
+                                       [lineScanner scanString:@"\n" intoString:nil];
+                               }
+                       }
+                       if (!processedAlias)
+                       {
+                               /* if we haven't written our line yet, append to end */
+                               [self _appendNewCellAliasLine:newStrCell aliasName:newStrAlias toString:aliasString];
+                       }
+
+                       /* add username to file name */
+                       NSMutableString * fileWriteCellAliasUname = [NSMutableString stringWithCapacity:0];
+                       [fileWriteCellAliasUname appendString:fileWriteCellAlias];
+                       [fileWriteCellAliasUname appendFormat:@"."];
+                       [fileWriteCellAliasUname appendString:userName];
                        
-               return YES;
+                       if (![aliasString writeToFile:fileWriteCellAliasUname atomically:YES encoding:NSASCIIStringEncoding error:nil])
+                       {
+                               [errorString setString:@"Could not write file: "];
+                               [errorString appendString:fileWriteCellAliasUname];
+                               [errorString appendFormat:@"  Continue?"];
+                               if (![self _continueAlertPanel:errorString titleText:@"File Error" firstButtonText:@"Continue" secondButtonText:@"Cancel"])
+
+                               {
+                                       return NO;
+                               }
+                       }
+               }
        }
        return YES;
 }