[38760] branches/gsoc08-framework/MacPorts_Framework

armahg at macports.org armahg at macports.org
Wed Jul 30 09:29:12 PDT 2008


Revision: 38760
          http://trac.macosforge.org/projects/macports/changeset/38760
Author:   armahg at macports.org
Date:     2008-07-30 09:29:11 -0700 (Wed, 30 Jul 2008)
Log Message:
-----------
Things are about to get messy with MPHelperTool. Need a sane place to revert to if they go really awry. This is it

Modified Paths:
--------------
    branches/gsoc08-framework/MacPorts_Framework/MPHelperTool.m
    branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.h
    branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.m
    branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.h
    branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.m
    branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.h
    branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.m
    branches/gsoc08-framework/MacPorts_Framework/MPNotifications.m
    branches/gsoc08-framework/MacPorts_Framework/MacPorts.Framework.xcodeproj/project.pbxproj

Modified: branches/gsoc08-framework/MacPorts_Framework/MPHelperTool.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPHelperTool.m	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPHelperTool.m	2008-07-30 16:29:11 UTC (rev 38760)
@@ -8,34 +8,181 @@
 
 #import <Cocoa/Cocoa.h>
 #import <Foundation/Foundation.h>
+#import <Security/Security.h>
 #import "MPInterpreter.h"
+#include <stdlib.h>
+#include <sys/stat.h>
 
 
 
-int main(int argc, char * const *argv) {
+// /////////////////////////////////////////////////////////////////////////////
+// exitCleanly
+//
+// Exits the program with the correct status and releases the autorelease pool.
+void exitCleanly(int code, NSAutoreleasePool *pool)
+{
+	[pool release];
+	exit(code);
+}
+
+
+
+//This code is adapted from :
+// http://forums.macrumors.com/showthread.php?t=508394
+
+//I will first try implementing this without any Authorization services.
+//I just want a helper tool whose user id is set to 0 and can self repair itself
+//I will be using message passing for IPC rather than piping or anything else
+//like that. Check on IRC if there are any dangers in doing that.
+
+
+
+
+//Usage 
+// ./MPHelperTool --self-repair srOptions --rec-count recOptions interpCmd
+// So argv is of size 6 ... no more no less 
+
+// srOptions is a C string with value of "yes" or "no" to tell us whether or not
+// to run self repair
+
+//recOptions is a number telling us how many times we have been called recursively
+
+//interpCmd is a the 
+
+int main(int argc, char const * argv[]) {
 	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 	
-	NSString * pathtoself = [[NSBundle mainBundle] pathForResource:@"MPHelperTool"
-															ofType:nil];
+	setuid(0);
+	NSLog(@"UID is %i", geteuid());	
+	//Check for right number of args
+	if (argc != 6) {
+		exitCleanly(TCL_ERROR , pool);
+	}
 	
-	NSLog(@"Path to executable is %@", pathtoself);
+	//The second thing to check for is recOptions ... This method should be called
+	//recursively at most once. Its a bit weird but I think from the code above,
+	//this tool repairs itself AND THEN proceeds to execute the required command all in
+	//one process. This means the number of recursive calls should not exceed one.
+	//If we fail to self repair at the first try, we should just exit.
+
+									 
+	int recOptions = [[NSString stringWithCString:argv[4] encoding:NSUTF8StringEncoding] intValue];
+	if (recOptions > 1) {
+		exitCleanly(TCL_ERROR, pool);
+	}
+	else {
+		++recOptions;
+	}
 	
-	if (argc == 2) {
-		MPInterpreter * interp = [MPInterpreter sharedInterpreter];
+	MPInterpreter * interp = [MPInterpreter sharedInterpreter];
+	NSString * interpCmd = [NSString stringWithCString:argv[5] encoding:NSUTF8StringEncoding];
+	NSString * _path_to_self = [[NSBundle mainBundle] pathForResource:@"MPHelperTool" 
+															   ofType:nil];
+	
+	//OSStatus status;
+	BOOL authenticatedMode = YES;
+	//AuthorizationRef auth;
+	//AuthorizationExternalForm extAuth;
+	
+	//This memory pointer should be valid till _path_to_self is freed or released
+	//in the autorelease pool .. in other words its save for our purposes
+	//and we dont' have to worry about releasing memory
+	const char * path_to_self = [_path_to_self cStringUsingEncoding:NSUTF8StringEncoding];
+	
+	if (!strcmp(argv[1], "--self-repair") && !strcmp(argv[2], "yes") )
+	{
+		NSLog(@"MacPortsFramework MPHelperTool main Self-repair. Starting");
+		// We have started ourself in self-repair mode.  This means that this executable is not owned by root and/or the setuid bit is not set.  We need to recover that...
+		struct stat st;
+        int fd_tool;
+		
+		
+		//We don't need this code for now
+		/* Recover the passed in AuthorizationRef.*/
+		
+		
+		/* Open tool exclusively, so noone can change it while we bless it */
+        fd_tool = open(path_to_self, O_NONBLOCK|O_RDONLY|O_EXLOCK, 0);
+		
+        if (fd_tool == -1)
+        {
+            NSLog(@"MacPortsFramework MPHelperTool main Self-Repair. Exclusive open while repairing tool failed: %d.",errno);
+			exitCleanly(-1,pool);
+        }
+		
+        if (fstat(fd_tool, &st))
+		{
+			NSLog(@"MacPortsFramework MPHelperTool main Self-Repair. fstat failed");
+            exitCleanly(-1,pool);
+		}
+        
+        if (st.st_uid != 0)
+		{
+            fchown(fd_tool, 0, st.st_gid);
+		}
+		
+		
+        /* Disable group and world writability and make setuid root. */
+        fchmod(fd_tool, (st.st_mode & (~(S_IWGRP|S_IWOTH))) | S_ISUID);
+		
+        close(fd_tool);
+		
+		NSLog(@"MacPortsFramework MPHelperTool main Self-repair. Complete");
+		authenticatedMode = YES;
+		
+		
+		/*/Hopefully this works
+		int result = [interp execute:_path_to_self 
+							withArgs:[NSArray arrayWithObjects:SELF_REPAIR, @"no", REC_COUNT, 
+									  [NSString stringWithFormat:@"%d", recOptions], interpCmd,  nil]];
+		
+		exitCleanly(result, pool);*/
+		
+		
+	}
+	else
+	{
+		//To Do
+		//Add code here to receive Authorization reference from somwhere
+		
+		authenticatedMode = YES;
+	}
+	
+	/* If we are not running as root we need to self-repair. But we don't want to do it more than once
+	 which means */
+	if (authenticatedMode && geteuid() != 0)
+	{
+		NSLog(@"MacPortsFramework MPHelperTool main Normal-Mode. Not running as root! Starting self-repair mode.");
+		
+		//We run again in self repair mode. I am assuming that this new "forked" process
+		// will be able to repair the binary and execute the command successfully ... 
+		//if it fails I guess i should return something to that effect?
+		int result = [interp execute:_path_to_self 
+			   withArgs:[NSArray arrayWithObjects:SELF_REPAIR, @"yes", REC_COUNT, 
+						 [NSString stringWithFormat:@"%d", recOptions], interpCmd,  nil]];
+		
+		
+		//Is the above method guaranteed to always complete before the
+		//program execution gets here?
+		exitCleanly(result, pool);
+		
+		
+	}
+	
+	//Now we can finally execute the method ... whew
+	if (interpCmd != nil) {
 		NSError * evalError;
-		++argv;
-		NSString * interpCmd = [NSString stringWithCString:*argv];
 		NSLog(@"Executin Tcl command %@", interpCmd);
 		
 		NSString * result = [interp evaluateStringAsString:interpCmd 
 													 error:&evalError];
 		if(result == nil && evalError) {
 			NSLog(@"Command %@ exited with Error %@", interpCmd, evalError);
-			return TCL_ERROR;
+			exitCleanly(TCL_ERROR,pool);
 		}
 		else {
 			NSLog(@"Command %@ returned %@", interpCmd, result);
-			return TCL_OK;
+			exitCleanly(TCL_OK, pool);
 		}
 		/*while(*argv != NULL) {
 			NSLog(@"Passed parameter is %@", [NSString stringWithCString:*argv]);

Modified: branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.h
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.h	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.h	2008-07-30 16:29:11 UTC (rev 38760)
@@ -43,6 +43,11 @@
 #include <tcl.h>  
 #import "MPNotifications.h"
 
+
+//Defining some flags for MPHelperTool
+#define SELF_REPAIR @"--self-repair"
+#define REC_COUNT @"--rec-count"
+
 #define	MPPackage				@"macports"
 #define MPPackageVersion		@"1.0"
 #define MP_DEFAULT_PKG_PATH		@"/Library/Tcl"
@@ -70,8 +75,8 @@
 + (MPInterpreter *)sharedInterpreter;
 
 - (Tcl_Interp *) sharedTclInterpreter;
+- (int) execute:(NSString *)pathToExecutable withArgs:(NSArray*)args;
 
-
 + (MPInterpreter *)sharedInterpreterWithPkgPath:(NSString *)path;
 - (id) initWithPkgPath:(NSString *)path;
 

Modified: branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.m	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPInterpreter.m	2008-07-30 16:29:11 UTC (rev 38760)
@@ -243,6 +243,17 @@
 
 #pragma Utilities
 
+- (int) execute:(NSString *)pathToExecutable withArgs:(NSArray *)args {
+	NSTask * task = [[NSTask alloc] init];
+	[task setLaunchPath:pathToExecutable];
+	[task setArguments:args];
+	[task launch];
+	[task waitUntilExit];
+	int status = [task terminationStatus];
+	[task release];
+	return status;
+}
+
 /*- (NSDictionary *)evaluateArrayAsString:(NSArray *)statement {
 	return [self evaluateStringAsString:[statement componentsJoinedByString:@" "]];
 }
@@ -257,10 +268,10 @@
 		Tcl_Obj * interpObj = Tcl_GetObjResult(_interpreter);
 		int length, errCode;
 		NSString * errString = [NSString stringWithUTF8String:Tcl_GetStringFromObj(interpObj, &length)];
-		NSLog(@"TclObj string is %@ with length %d", errString , length);
+		//NSLog(@"TclObj string is %@ with length %d", errString , length);
 		errCode = Tcl_GetErrno();
-		NSLog(@"Errno Id is %@ with value %d", [NSString stringWithUTF8String:Tcl_ErrnoId()], errCode);
-		NSLog(@"Errno Msg is %@", [NSString stringWithUTF8String:Tcl_ErrnoMsg(errCode)]);
+		//NSLog(@"Errno Id is %@ with value %d", [NSString stringWithUTF8String:Tcl_ErrnoId()], errCode);
+		//NSLog(@"Errno Msg is %@", [NSString stringWithUTF8String:Tcl_ErrnoMsg(errCode)]);
 		
 		//Handle errors here ... Framework users can do !mportError to find out if
 		//method was successful

Modified: branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.h
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.h	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.h	2008-07-30 16:29:11 UTC (rev 38760)
@@ -43,6 +43,7 @@
 
 - (void)testInitialization;
 - (void)testGetVariableAsArray;
+//- (void)testMPHelperTool;
 //- (void)testMutableDictionaryFromTclListAsString;
 //- (void)testEvaluateStringAsString;
 

Modified: branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.m	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPInterpreterTest.m	2008-07-30 16:29:11 UTC (rev 38760)
@@ -59,6 +59,16 @@
  
 
 /*
+- (void)testMPHelperTool {
+	
+	//Interesting ... we'll see who MPInterpreter belongs to
+	//at the time of execution MPHelperTool ... or MacPorts.Framework
+	[interp execute:[[NSBundle bundleForClass:MPInterpreter] pathForResource:@"MPHelperTool" ofType:nil] 
+		   withArgs:[NSArray arrayWithObjects:@"--sel-repair", @"no", @"--rec-count", 
+					 @"0", @"mportselfupdate", nil]];
+}
+
+/*
  Having trouble coming up with test cases for the methods below. Speak to Randall
  about that.
  *

Modified: branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.h
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.h	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.h	2008-07-30 16:29:11 UTC (rev 38760)
@@ -42,7 +42,7 @@
 
 }
 
--(void) testMPHelperTool;
+
 -(void) testPortCreation;
 -(void) testPrefix;
 -(void) testSources;
@@ -52,5 +52,6 @@
 -(void) testSync;
 -(void) testVersion;
 //-(void) testInstall;
+-(void) testMPHelperTool;
 
 @end

Modified: branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.m	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPMacPortsTest.m	2008-07-30 16:29:11 UTC (rev 38760)
@@ -111,7 +111,8 @@
 						 pathForResource:@"MPHelperTool" 
 						 ofType:nil]];
 	
-	NSArray * args = [NSArray arrayWithObjects:@"return [macports::version]", nil];
+	NSArray * args = [NSArray arrayWithObjects:SELF_REPAIR, @"no",
+					  REC_COUNT, @"0", @"return [macports::version]", nil];
 	[task setArguments:args];
 	
 	[task launch];

Modified: branches/gsoc08-framework/MacPorts_Framework/MPNotifications.m
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MPNotifications.m	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MPNotifications.m	2008-07-30 16:29:11 UTC (rev 38760)
@@ -85,7 +85,7 @@
 						[NSNumber numberWithInt:0], MPMSG, [NSNumber numberWithInt:0], MPINFO, 
 						[NSNumber numberWithInt:0], MPWARN, [NSNumber numberWithInt:0], MPERROR, 
 						[NSNumber numberWithInt:1], MPDEBUG, [NSNumber numberWithInt:0], MPALL, nil];
-		NSLog(@"Dictionary is %@ ", [blockOptions description]);
+		//NSLog(@"Dictionary is %@ ", [blockOptions description]);
 	}
 	return self;
 }

Modified: branches/gsoc08-framework/MacPorts_Framework/MacPorts.Framework.xcodeproj/project.pbxproj
===================================================================
--- branches/gsoc08-framework/MacPorts_Framework/MacPorts.Framework.xcodeproj/project.pbxproj	2008-07-30 12:30:35 UTC (rev 38759)
+++ branches/gsoc08-framework/MacPorts_Framework/MacPorts.Framework.xcodeproj/project.pbxproj	2008-07-30 16:29:11 UTC (rev 38760)
@@ -56,6 +56,7 @@
 		6ED12AFB0E3E9F980026773D /* MPNotifications.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E270D070E158CED00BAE687 /* MPNotifications.h */; };
 		6ED12AFC0E3E9FA60026773D /* MPNotifications.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E270D080E158CED00BAE687 /* MPNotifications.m */; };
 		6ED12B060E3EA9E30026773D /* init.tcl in Resources */ = {isa = PBXBuildFile; fileRef = 48E9939E0C82CEB000219DDF /* init.tcl */; };
+		6ED12C9E0E40C3320026773D /* template.c in Resources */ = {isa = PBXBuildFile; fileRef = 6ED12C9D0E40C3320026773D /* template.c */; };
 		8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
 		8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
 /* End PBXBuildFile section */
@@ -118,6 +119,8 @@
 		6ED12A540E3E55DF0026773D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
 		6ED12AA20E3E7E7C0026773D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
 		6ED12AA60E3E7E900026773D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+		6ED12C2D0E405E660026773D /* finkLauncher.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = finkLauncher.c; sourceTree = "<group>"; };
+		6ED12C9D0E40C3320026773D /* template.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = template.c; sourceTree = "<group>"; };
 		8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
 		8DC2EF5B0486A6940098B216 /* MacPorts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MacPorts.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
@@ -288,6 +291,8 @@
 			isa = PBXGroup;
 			children = (
 				6ED12A4E0E3E55660026773D /* MPHelperTool.m */,
+				6ED12C2D0E405E660026773D /* finkLauncher.c */,
+				6ED12C9D0E40C3320026773D /* template.c */,
 			);
 			name = MPHelperTool;
 			sourceTree = "<group>";
@@ -418,6 +423,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				6ED12B060E3EA9E30026773D /* init.tcl in Resources */,
+				6ED12C9E0E40C3320026773D /* template.c in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20080730/50f30df1/attachment.html 


More information about the macports-changes mailing list