Moving the framework into dev branch

git-svn-id: https://svn.macports.org/repository/macports/branches/gsoc15-pallet@136747 d073be05-634f-4543-b044-5fe20cf6d1d6
This commit is contained in:
Kyle Sammons
2015-05-25 20:13:33 +00:00
56 changed files with 14386 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,497 @@
/*
File: BetterAuthorizationSampleLibInstallTool.c
Contains: Tool to install BetterAuthorizationSampleLib-based privileged helper tools.
Written by: DTS
Copyright: Copyright (c) 2007 Apple Inc. All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
// Allows access to path information associated with tool and plist installation
// from BetterAuthorizationSampleLib.h
#define BAS_PRIVATE 1
#include "BetterAuthorizationSampleLib.h"
extern char **environ;
static int RunLaunchCtl(
bool junkStdIO,
const char *command,
const char *plistPath
)
// Handles all the invocations of launchctl by doing the fork() + execve()
// for proper clean-up. Only two commands are really supported by our
// implementation; loading and unloading of a job via the plist pointed at
// (const char *) plistPath.
{
int err;
const char * args[5];
pid_t childPID;
pid_t waitResult;
int status;
// Pre-conditions.
assert(command != NULL);
assert(plistPath != NULL);
// Make sure we get sensible logging even if we never get to the waitpid.
status = 0;
// Set up the launchctl arguments. We run launchctl using StartupItemContext
// because, in future system software, launchctl may decide on the launchd
// to talk to based on your Mach bootstrap namespace rather than your RUID.
args[0] = "/bin/launchctl";
args[1] = command; // "load" or "unload"
args[2] = "-w";
args[3] = plistPath; // path to plist
args[4] = NULL;
fprintf(stderr, "launchctl %s %s '%s'\n", args[1], args[2], args[3]);
// Do the standard fork/exec dance.
childPID = fork();
switch (childPID) {
case 0:
// child
err = 0;
// If we've been told to junk the I/O for launchctl, open
// /dev/null and dup that down to stdin, stdout, and stderr.
if (junkStdIO) {
int fd;
int err2;
fd = open("/dev/null", O_RDWR);
if (fd < 0) {
err = errno;
}
if (err == 0) {
if ( dup2(fd, STDIN_FILENO) < 0 ) {
err = errno;
}
}
if (err == 0) {
if ( dup2(fd, STDOUT_FILENO) < 0 ) {
err = errno;
}
}
if (err == 0) {
if ( dup2(fd, STDERR_FILENO) < 0 ) {
err = errno;
}
}
err2 = close(fd);
if (err2 < 0) {
err2 = 0;
}
if (err == 0) {
err = err2;
}
}
if (err == 0) {
err = execve(args[0], (char **) args, environ);
}
if (err < 0) {
err = errno;
}
_exit(EXIT_FAILURE);
break;
case -1:
err = errno;
break;
default:
err = 0;
break;
}
// Only the parent gets here. Wait for the child to complete and get its
// exit status.
if (err == 0) {
do {
waitResult = waitpid(childPID, &status, 0);
} while ( (waitResult == -1) && (errno == EINTR) );
if (waitResult < 0) {
err = errno;
} else {
assert(waitResult == childPID);
if ( ! WIFEXITED(status) || (WEXITSTATUS(status) != 0) ) {
err = EINVAL;
}
}
}
fprintf(stderr, "launchctl -> %d %ld 0x%x\n", err, (long) childPID, status);
return err;
}
static int CopyFileOverwriting(
const char *sourcePath,
mode_t destMode,
const char *destPath
)
// Our own version of a file copy. This routine will either handle
// the copy of the tool binary or the plist file associated with
// that binary. As the function name suggests, it writes over any
// existing file pointed to by (const char *) destPath.
{
int err;
int junk;
int sourceFD;
int destFD;
char buf[65536];
// Pre-conditions.
assert(sourcePath != NULL);
assert(destPath != NULL);
(void) unlink(destPath);
destFD = -1;
err = 0;
sourceFD = open(sourcePath, O_RDONLY);
if (sourceFD < 0) {
err = errno;
}
if (err == 0) {
destFD = open(destPath, O_CREAT | O_EXCL | O_WRONLY, destMode);
if (destFD < 0) {
err = errno;
}
}
if (err == 0) {
ssize_t bytesReadThisTime;
ssize_t bytesWrittenThisTime;
ssize_t bytesWritten;
do {
bytesReadThisTime = read(sourceFD, buf, sizeof(buf));
if (bytesReadThisTime < 0) {
err = errno;
}
bytesWritten = 0;
while ( (err == 0) && (bytesWritten < bytesReadThisTime) ) {
bytesWrittenThisTime = write(destFD, &buf[bytesWritten], bytesReadThisTime - bytesWritten);
if (bytesWrittenThisTime < 0) {
err = errno;
} else {
bytesWritten += bytesWrittenThisTime;
}
}
} while ( (err == 0) && (bytesReadThisTime != 0) );
}
// Clean up.
if (sourceFD != -1) {
junk = close(sourceFD);
assert(junk == 0);
}
if (destFD != -1) {
junk = close(destFD);
assert(junk == 0);
}
fprintf(stderr, "copy '%s' %#o '%s' -> %d\n", sourcePath, (int) destMode, destPath, err);
return err;
}
static int InstallCommand(
const char * bundleID,
const char * toolSourcePath,
const char * plistSourcePath
)
// Heavy lifting function for handling all the necessary steps to install a
// helper tool in the correct location, with the correct permissions,
// and call launchctl in order to load it as a current job.
{
int err;
char toolDestPath[PATH_MAX];
char plistDestPath[PATH_MAX];
struct stat sb;
static const mode_t kDirectoryMode = ACCESSPERMS & ~(S_IWGRP | S_IWOTH);
static const mode_t kExecutableMode = ACCESSPERMS & ~(S_IWGRP | S_IWOTH);
static const mode_t kFileMode = DEFFILEMODE & ~(S_IWGRP | S_IWOTH);
// Pre-conditions.
assert(bundleID != NULL);
assert(toolSourcePath != NULL);
assert(plistSourcePath != NULL);
(void) snprintf(toolDestPath, sizeof(toolDestPath), kBASToolPathFormat, bundleID);
(void) snprintf(plistDestPath, sizeof(plistDestPath), kBASPlistPathFormat, bundleID);
// Stop the helper tool if it's currently running.
(void) RunLaunchCtl(true, "unload", plistDestPath);
// Create the PrivilegedHelperTools directory. The owner will be "root" because
// we're running as root (our EUID is 0). The group will be "admin" because
// it's inherited from "/Library". The permissions will be rwxr-xr-x because
// of kDirectoryMode combined with our umask.
err = mkdir(kBASToolDirPath, kDirectoryMode);
if (err < 0) {
err = errno;
}
fprintf(stderr, "mkdir '%s' %#o -> %d\n", kBASToolDirPath, kDirectoryMode, err);
if ( (err == 0) || (err == EEXIST) ) {
err = stat(kBASToolDirPath, &sb);
if (err < 0) {
err = errno;
}
}
// /Library/PrivilegedHelperTools may have come from a number of places:
//
// A. We may have just created it. In this case it will be
// root:admin rwxr-xr-x.
//
// B. It may have been correctly created by someone else. By definition,
// that makes it root:wheel rwxr-xr-x.
//
// C. It may have been created (or moved here) incorrectly (or maliciously)
// by someone else. In that case it will be u:g xxxxxxxxx, where u is
// not root, or root:g xxxxwxxwx (that is, root-owned by writeable by
// someone other than root).
//
// In case A, we want to correct the group. In case B, we want to do
// nothing. In case C, we want to fail.
if (err == 0) {
if ( (sb.st_uid == 0) && (sb.st_gid == 0) ) {
// case B -- do nothing
} else if ( (sb.st_uid == 0) && (sb.st_gid != 0) && ((sb.st_mode & ALLPERMS) == kDirectoryMode) ) {
// case A -- fix the group ID
//
// This is safe because /Library is sticky and the file is owned
// by root, which means that only root can move it. Also, we
// don't have to worry about malicious files existing within the
// directory because its only writeable by root.
err = chown(kBASToolDirPath, -1, 0);
if (err < 0) {
err = errno;
}
fprintf(stderr, "chown -1:0 '%s' -> %d\n", kBASToolDirPath, err);
} else {
fprintf(stderr, "bogus perms on '%s' %d:%d %o\n", kBASToolDirPath, (int) sb.st_uid, (int) sb.st_gid, (int) sb.st_mode);
err = EPERM;
}
}
// Then create the known good copy. The ownership and permissions
// will be set appropriately, as described in the comments for mkdir.
// We don't have to worry about atomicity because this tool won't be
// looked at until our plist is installed.
if (err == 0) {
err = CopyFileOverwriting(toolSourcePath, kExecutableMode, toolDestPath);
}
// For the plist, our caller has created the file in /tmp and we just copy it
// into the correct location. This ensures that the file is complete
// and valid before anyone starts looking at it and will also overwrite
// any existing file with this new version.
//
// Since we have to read/write in the file byte by byte to make sure that
// the file is complete we are rolling our own 'copy'. This clearly is
// ignoring atomicity since we do not roll back to the state of 'what was
// previously there' if there is an error; rather, whatever has been
// written up to that point of granular failure /is/ the state of the
// plist file.
if (err == 0) {
err = CopyFileOverwriting(plistSourcePath, kFileMode, plistDestPath);
}
// Use launchctl to load our job. The plist file starts out disabled,
// so we pass "-w" to enable it permanently.
if (err == 0) {
err = RunLaunchCtl(false, "load", plistDestPath);
}
return err;
}
static int EnableCommand(
const char *bundleID
)
// Utility function to call through to RunLaunchCtl in order to load a job
// given by the path contructed from the (const char *) bundleID.
{
int err;
char plistPath[PATH_MAX];
// Pre-condition.
assert(bundleID != NULL);
(void) snprintf(plistPath, sizeof(plistPath), kBASPlistPathFormat, bundleID);
err = RunLaunchCtl(false, "load", plistPath);
return err;
}
static int TerminateCommand(
const char *bundleID
)
// Utility function to call through to RunLaunchCtl in order to terminate a job
// given by the path contructed from the (const char *) bundleID.
{
int err;
char plistPath[PATH_MAX];
// Pre-condition.
assert(bundleID != NULL);
(void) snprintf(plistPath, sizeof(plistPath), kBASPlistPathFormat, bundleID);
err = RunLaunchCtl(false, "unload", plistPath);
return err;
}
int main(int argc, char **argv)
{
int err;
// Print our PID so that the app can avoid creating zombies.
fprintf(stdout, kBASAntiZombiePIDToken1 "%ld" kBASAntiZombiePIDToken2 "\n", (long) getpid());
fflush(stdout);
// On the client side, AEWP only gives a handle to stdout, so we dup stdout
// downto stderr for the rest of this tool. This ensures that all our output
// makes it to the client.
err = dup2(STDOUT_FILENO, STDERR_FILENO);
if (err < 0) {
err = errno;
} else {
err = 0;
}
// Set up the standard umask. The goal here is to be robust in the
// face of common environmental changes, not to resist a malicious attack.
// Also sync the RUID to the 0 because launchctl keys off the RUID (at least
// on 10.4.x).
if (err == 0) {
(void) umask(S_IWGRP | S_IWOTH);
err = setuid(0);
if (err < 0) {
fprintf(stderr, "setuid\n");
err = EINVAL;
}
}
if ( (err == 0) && (argc < 2) ) {
fprintf(stderr, "usage\n");
err = EINVAL;
}
// The first argument is the command. Switch off that and extract the
// remaining arguments and pass them to our command routines.
if (err == 0) {
if ( strcmp(argv[1], kBASInstallToolInstallCommand) == 0 ) {
if (argc == 5) {
err = InstallCommand(argv[2], argv[3], argv[4]);
} else {
fprintf(stderr, "usage3\n");
err = EINVAL;
}
} else if ( strcmp(argv[1], kBASInstallToolEnableCommand) == 0 ) {
if (argc == 3) {
err = EnableCommand(argv[2]);
} else {
fprintf(stderr, "usage4\n");
err = EINVAL;
}
} else if (strcmp(argv[1], kBASInstallToolTerminateCommand) == 0) {
if (argc == 3) {
err = TerminateCommand(argv[2]);
} else {
fprintf(stderr, "usage4\n");
err = EINVAL;
}
} else {
fprintf(stderr, "usage2\n");
err = EINVAL;
}
}
// Write "oK" to stdout and quit. The presence of the "oK" on the last
// line of output is used by the calling code to detect success.
if (err == 0) {
fprintf(stderr, kBASInstallToolSuccess "\n");
} else {
fprintf(stderr, kBASInstallToolFailure "\n", err);
}
return (err == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
Binary file not shown.
Binary file not shown.
+33
View File
@@ -0,0 +1,33 @@
<?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>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>org.macports.frameworks.macports</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleSignature</key>
<string>Randall Wood</string>
<key>CFBundleVersion</key>
<string>1.1</string>
<key>NSPrincipalClass</key>
<string></string>
<key>LSMinimumSystemVersionByArchitecture</key>
<dict>
<key>i386</key>
<string>10.4.0</string>
<key>x86_64</key>
<string>10.6.0</string>
</dict>
</dict>
</plist>
+36
View File
@@ -0,0 +1,36 @@
/*
* MPHelperCommon.c
* MacPorts.Framework
*
* Created by George Armah on 7/31/08.
* Copyright 2008 Lafayette College. All rights reserved.
*
*/
#include "MPHelperCommon.h"
/*
IMPORTANT
---------
This array must be exactly parallel to the kMPHelperCommandProcs array
in "MPHelperTool.m".
*/
const BASCommandSpec kMPHelperCommandSet[] = {
{ kMPHelperEvaluateTclCommand, //commandName
kMPHelperEvaluateTclRightsName, //rightName
"default", //rightDefaultRule -- by default, you have to have admin credentials
NULL, //rightDescriptionKey
NULL // userData ... I might use this to pass the NSError object later on
},
{ NULL, //the array is null terminated
NULL,
NULL,
NULL,
NULL
}
};
+65
View File
@@ -0,0 +1,65 @@
/*
* MPHelperCommon.h
* MacPorts.Framework
*
* Created by George Armah on 7/31/08.
* Copyright 2008 Lafayette College. All rights reserved.
*
*/
#ifndef _MPHELPERCOMMON_H
#define _MPHELPERCOMMON_H
#include "BetterAuthorizationSampleLib.h"
#include <tcl.h>
#define asl_NSLog(client, msg, level, format, ...) asl_log(client, msg, level, "%s", [[NSString stringWithFormat:format, ##__VA_ARGS__] UTF8String])
#ifndef ASL_KEY_FACILITY
# define ASL_KEY_FACILITY "Facility"
#endif
//We need only one command for this Tool
#define kMPHelperEvaluateTclCommand "EvaluateTcl"
// authorization right name
#define kMPHelperEvaluateTclRightsName "com.MacPorts.MacPortsFramework.EvaluateTcl"
// request keys
// Should I put the NSError object in the request dictionary ?
// I'll try that for now and see how it goes
//String to be Evlauted
#define kTclStringToBeEvaluated "TclString" //CFString
//Tcl MacPorts Package Initialization Path
#define kTclInterpreterInitPath "TclInitPath" //CFString
//Tcl interpInit.tcl Path
#define kInterpInitFilePath "InterpInitTclFilePath" //CFString
//File Descriptor for server file
#define kServerFileDescriptor "ServerFileDescriptor" //CFNumber
//File path for IPC socket
#define kServerFileSocketPath "ServerFileSocketPath" //CFString
//response keys
#define kTclStringEvaluationResult "TclStringEvaluationResult" //CFString
#define kTclReturnCode "TclReturnCode" //CFNumber (TCL_OK, TCL_ERROR etc.)
//Key for Testing Distributed Object implementation
#define kMPInterpreterDistObj "MPInterpreterDistObj"
extern const BASCommandSpec kMPHelperCommandSet[];
#endif
File diff suppressed because it is too large Load Diff
+119
View File
@@ -0,0 +1,119 @@
/*
File: MPHelperNotificationsCommon.h
Contains: Common code between client and server.
Written by: DTS
Copyright: Copyright (c) 2005 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Change History (most recent first):
$Log: MPHelperNotificationsCommon.h,v $
Revision 1.1 2005/05/17 12:19:20
First checked in.
*/
#ifndef _COMMON_H
#define _COMMON_H
/////////////////////////////////////////////////////////////////
// System interfaces
#include <CoreServices/CoreServices.h>
// Project interfaces
#include "MPHelperNotificationsProtocol.h"
/////////////////////////////////////////////////////////////////
extern int MoreUNIXErrno(int result);
extern int MoreUNIXIgnoreSIGPIPE(void);
extern int MoreUNIXRead( int fd, void *buf, size_t bufSize, size_t *bytesRead );
extern int MoreUNIXWrite(int fd, const void *buf, size_t bufSize, size_t *bytesWritten);
// The above routines are taken from the MoreIsBetter library.
extern int MoreUNIXSetNonBlocking(int fd);
typedef void (*SignalSocketCallback)(const siginfo_t *sigInfo, void *refCon);
// This callback is called when a signal occurs. It's called in the
// context of the runloop specified when you registered the callback.
// sigInfo describes the signal and refCon is the value you supplied
// when you registered the callback.
extern int InstallSignalToSocket(
const sigset_t * sigSet,
CFRunLoopRef runLoop,
CFStringRef runLoopMode,
SignalSocketCallback callback,
void * refCon
);
// A method for routing signals to a runloop-based program.
//
// sigSet is the set of signals that you're interested in.
// Use the routines documented in <x-man-page://3/sigsetopts>
// to construct this.
//
// runLoop and runLoopMode specify how you want the callback
// to be run. You typically pass CFRunLoopGetCurrent and
// kCFRunLoopDefaultMode.
//
// callback is the routine you want called, and refCon is an
// uninterpreted value that's passed to that callback.
//
// The function result is an errno-style error code.
//
// IMPORTANT:
// You can only call this routine once for any given application;
// you must register all of the signals you're interested in at that
// time. There is no way to deregister.
#endif
extern void DebugPrintDescriptorTable(void);
// Prints a nice dump of the file descriptor table to stdout.
extern void InitPacketHeader(PacketHeader *packet, OSType packetType, size_t packetSize, Boolean rpc);
// Initialises the PacketHeader structure with the values specified
// in the parameters. The rpc parameter controls whether the fID
// field is set to kPacketIDNone (rpc false, hence no ID) or an
// incrementing sequence number (rpc true).
+183
View File
@@ -0,0 +1,183 @@
/*
File: MPHelperNotificationsProtocol.h
Contains: Definition of the communication protocol between client and server.
Written by: DTS
Copyright: Copyright (c) 2005 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
("Apple") in consideration of your agreement to the following terms, and your
use, installation, modification or redistribution of this Apple software
constitutes acceptance of these terms. If you do not agree with these terms,
please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
copyrights in this original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or without
modifications, in source and/or binary forms; provided that if you redistribute
the Apple Software in its entirety and without modifications, you must retain
this notice and the following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks or logos of
Apple Computer, Inc. may be used to endorse or promote products derived from the
Apple Software without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any patent rights that
may be infringed by your derivative works or by other works in which the Apple
Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Change History (most recent first):
$Log: MPHelperNotificationsProtocol.h,v $
Revision 1.1 2005/05/17 12:19:23
First checked in.
*/
#ifndef _PROTOCOL_H
#define _PROTOCOL_H
/////////////////////////////////////////////////////////////////
// System interfaces
#include <CoreServices/CoreServices.h>
#include <inttypes.h>
/////////////////////////////////////////////////////////////////
// Packet types
enum {
kPacketTypeGoodbye = 'GDBY', // sent by client to server before signing off
kPacketTypeNOP = 'NOOP', // no operation, test for client/server RPC
kPacketTypeReply = 'RPLY', // all RPC replies are of this type
kPacketTypeWhisper = 'WSPR', // client/server RPC to print message on server
kPacketTypeShout = 'SHOU', // sent by client to server, which echoes it to all listening clients
kPacketTypeListen = 'LSTN', // client/server RPC to register for shouts
kPacketTypeQuit = 'QUIT' // client/server RPC to tell server to quit
};
// Well known packet IDs (for the fID field of the packet header).
// kPacketIDFirst is just a suggestion. The server doesn't require
// that the client use sequential IDs starting from 1; the IDs are
// for the client to choose. However, the use of kPacketIDNone for
// some packets (those that don't have a reply) is a hard requirement
// in the server.
enum {
kPacketIDNone = 0,
kPacketIDFirst = 1
};
// kPacketMagic is first four bytes of every packet. If the packet stream
// gets out of sync, this will quickly detect the problem.
enum {
kPacketMagic = 'LSPM' // for Local Server Packet Magic
};
// kPacketMaximumSize is an arbitrary limit, chosen so that we can detect
// if the packet streams get out of sync or if a client goes mad.
enum {
kPacketMaximumSize = 100 * 1024 // just basic sanity checks
};
// IMPORTANT:
// The following structures define the packets sent between the client and
// the server. For a network protocol you'd need to worry about byte ordering,
// but this isn't a network protocol (it always stays on the same machine) so
// I don't have to worry. However, I do need to worry about having
// size invariant types (so that 32- and 64-bit clients and servers are
// all compatible) and structure alignment (so that code compiled by different
// compilers is compatible). Size invariant types is easy, and represented
// by the structures below. Alignment is trickier, and I'm mostly just
// glossing over the issue right now.
// PacketHeader is the header at the front of every packet.
struct PacketHeader {
OSType fMagic; // must be kPacketMagic
OSType fType; // kPacketTypeGoodbye etc
int32_t fID; // kPacketIDNone or some other value
uint32_t fSize; // includes size of header itself
};
typedef struct PacketHeader PacketHeader;
struct PacketGoodbye { // reply: n/a
PacketHeader fHeader; // fType is kPacketTypeGoodbye, fID must be kPacketIDNone
char fMessage[32]; // Just for fun.
};
typedef struct PacketGoodbye PacketGoodbye;
struct PacketNOP { // reply: PacketReply
PacketHeader fHeader; // fType is kPacketTypeNOP, fID echoed
};
typedef struct PacketNOP PacketNOP;
struct PacketReply { // reply: n/a
PacketHeader fHeader; // fType is kPacketTypeReply, fID is ID of request
int32_t fErr; // result of operation, errno-style
};
typedef struct PacketReply PacketReply;
struct PacketWhisper { // reply: PacketReply
PacketHeader fHeader; // fType is kPacketTypeWhisper, fID echoed
char fMessage[32]; // message to print
};
typedef struct PacketWhisper PacketWhisper;
struct PacketShout { // reply: none
PacketHeader fHeader; // fType is kPacketTypeShout, fID must be kPacketIDNone
char fMessage[500]; // message for each of the clients
};
typedef struct PacketShout PacketShout;
// Shouts are echoed to anyone who listens, including sender.
struct PacketListen { // reply: PacketReply
PacketHeader fHeader; // fType is kPacketTypeListen, fID echoed
};
typedef struct PacketListen PacketListen;
struct PacketQuit { // reply: PacketReply
PacketHeader fHeader; // fType is kPacketTypeQuit, fID echoed
};
typedef struct PacketQuit PacketQuit;
// IMPORTANT:
// The location of the kServerAddress socket file is intimately tied to the
// security of the server. The file should be placed in a directory that's
// read access to everyone who needs access to the service, but only write
// accessible to the UID that's running the server. Failure to follow this
// guideline may make your server subject to security exploits.
//
// To prevent this sort of silliness I require that the socket be created
// in a directory owned by the server's user ("com.apple.dts.CFLocalServer")
// within a directory that's sticky ("/var/tmp", not "/tmp" because that's
// periodically cleaned up). See SafeBindUnixDomainSocket (in "Server.c") for
// the details about how I achieve this.
#define kServerSocketPath "/var/tmp/macports/org.macports.framework.ipc.socket"
#define MPSEPARATOR @"_&MP&_"
#endif
File diff suppressed because it is too large Load Diff
+189
View File
@@ -0,0 +1,189 @@
//
// MPHelperToolIPCTester.m
// MacPorts.Framework
//
// Created by George Armah on 8/24/08.
// Copyright 2008 Lafayette College. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <MacPorts/MacPorts.h>
@interface PortManipulator : NSObject {
}
-(BOOL) installUninstallManipulation:(NSString *)portName;
-(BOOL) selfUpdate;
-(void) registerForLocalNotifications;
@end
@implementation PortManipulator
-(id) init {
self = [super init];
if (self != nil) {
//[self registerForLocalNotifications];
}
return self;
}
-(void) registerForLocalNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:MPINFO
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:MPMSG
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:MPERROR
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:MPWARN
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:MPDEBUG
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:MPDEFAULT
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(respondToLocalNotification:)
name:@"testMacPortsNotification"
object:nil];
}
-(void) respondToLocalNotification:(NSNotification *)notification {
id sentDict = [notification userInfo];
//Just NSLog it for now
if(sentDict == nil)
NSLog(@"MPMacPorts received notification with empty userInfo Dictionary");
else
NSLog(@"MPMacPorts received notification with userInfo %@" , [sentDict description]);
}
-(BOOL) selfUpdate {
NSError *err = nil;
[[MPMacPorts sharedInstance] selfUpdate:&err];
if( err != nil) {
NSLog(@"%@", [err description]);
return NO;
}
return YES;
}
-(BOOL) installUninstallManipulation:(NSString *)portName {
BOOL ret = NO;
MPRegistry * registry = [MPRegistry sharedRegistry];
MPMacPorts * port = [MPMacPorts sharedInstance];
// Check if portName is installed
unsigned int installed = [[registry installed:portName] count];
// Search for it
NSDictionary * searchResult = [port search:portName];
NSArray * keyArray = [searchResult allKeys];
MPPort * foundPort = [searchResult objectForKey:[keyArray objectAtIndex:0]];
// If it is installed
if (installed > 0) {
NSError * uError;
//Attempt to uninstall it
[foundPort uninstallWithVersion:nil error:&uError];
//Check for error
if (uError != nil) {
NSLog(@"\n\nUninstallation of %@ failed with error %@", portName, uError);
//I guess we should just return here
return ret;
}
//Uninstallation was successful ... now check registry to make sure its gone
installed = [[registry installed:portName] count];
if (installed > 0) { //Uh oh ... is this suppose to happen?
NSLog(@"%@ is still installed after successful uninstall operation ... double check this from commandline", portName);
//for now return
return ret;
}
else { // For now end here later on ... add more code to restore system to its original state ... hmm i could just
// call this method twice
ret = YES;
return ret;
}
}
else {
NSError * uError;
//Attempt to install it
[foundPort installWithOptions:nil variants:nil error:&uError];
//Check for error
if (uError != nil) {
NSLog(@"\n\nInstallation of %@ failed with error %@", portName, uError);
//I guess we should just return here
return ret;
}
//Installation was successful ... now check registry to make sure its gone
installed = [[registry installed:portName] count];
if (installed == 0) { //Uh oh ... is this suppose to happen?
NSLog(@"%@ is not installed after successful install operation ... double check this from commandline", portName);
//for now return
return ret;
}
else { // For now end here later on ... add more code to restore system to its original state ... hmm i could just
// call this method twice
ret = YES;
return ret;
}
}
NSLog(@"We shouldn't be here");
return YES;
}
@end
int main(int argc, char const * argv[]) {
[[MPMacPorts sharedInstance] setAuthorizationMode:YES];
PortManipulator * pm = [[PortManipulator alloc] init];
if([pm installUninstallManipulation:@"pngcrush"]) {
NSLog(@"pngcrush INSTALLATION SUCCESSFUL");
}
else {
NSLog(@"pngcrush INSTALLATION UNSUCCESSFUL");
}
if([pm selfUpdate]) {
NSLog(@"SELFUPDATE SUCCESSFUL");
}
else {
NSLog(@"SELFUPDATE UNSUCCESSFUL");
}
return 0;
}
+22
View File
@@ -0,0 +1,22 @@
//
// MPHelperToolTest.h
// MacPorts.Framework
//
// Created by George Armah on 8/5/08.
// Copyright 2008 Lafayette College. All rights reserved.
//
#import <SenTestingKit/SenTestingKit.h>
#import <Security/Security.h>
#import "MPInterpreter.h"
@interface MPHelperToolTest : SenTestCase {
MPInterpreter * interp;
}
//-(void) testMPHelperToolWithoutRights;
@end
+42
View File
@@ -0,0 +1,42 @@
//
// MPHelperToolTest.m
// MacPorts.Framework
//
// Created by George Armah on 8/5/08.
// Copyright 2008 Lafayette College. All rights reserved.
//
#import "MPHelperToolTest.h"
@implementation MPHelperToolTest
-(void) setUp {
interp = [MPInterpreter sharedInterpreter];
}
-(void) tearDown {
}
//- (void) testMPHelperToolWithoutRights {
// AuthorizationRef authRef;
//
//
// OSStatus junk;
//
//
// junk = AuthorizationCreate (NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef);
// assert(junk == noErr);
//
// [interp setAuthorizationRef:authRef];
//
// NSString * result = [interp evaluateStringWithMPHelperTool:@"mportsync"];
//
// NSLog(@"Result is %@" , result);
// STAssertTrue ( [result isEqualToString:@"TCL COMMAND EXECUTION SUCCEEDED YAAY!:"], \
// @"Result should succeed so long as we enter credentials");
//}
//
@end
+108
View File
@@ -0,0 +1,108 @@
/*
* $Id$
* MacPorts.Framework
*
* Authors:
* Randall H. Wood <rhwood@macports.org>
*
* Copyright (c) 2007 Randall H. Wood <rhwood@macports.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright owner nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*!
@header
The MPIndex maintains an in-memory cache of all available ports and their
install status.
*/
#import <Cocoa/Cocoa.h>
#import "MPMacPorts.h"
#import "MPPort.h"
#define MPIndexWillSetIndex @"org.macports.framework.index.willSetIndex"
#define MPIndexDidSetIndex @"org.macports.framework.index.didSetIndex"
/*!
@class MPIndex
@abstract Index of all ports
@discussion Maintains an in-memory cache of all available ports and their
install status. The MPIndex class is analogous to the PortIndex files for every
port collection (most users have just one collection listed in
/opt/local/etc/macports/sources.conf).
*/
@interface MPIndex : MPMutableDictionary {
}
/*!
@brief Initialize a newly allocated index with enough memory for numItems ports
@param numItems The number of ports that the index will initially have capacity for
*/
- (id)initWithCapacity:(unsigned)numItems;
/*!
@brief Returns a new array conaining of all available ports
*/
- (NSArray *)ports;
/*!
@brief Returns a new array of all port names
*/
- (NSArray *)portNames;
/*!
@brief Loads all ports into the index from the MacPorts backend
*/
- (void)setIndex;
/*!
@brief Returns the port with the given name
@param name The name of the port
*/
- (MPPort *)port:(NSString *)name;
/*!
@brief Returns an enumerator of all ports
*/
- (NSEnumerator *)portEnumerator;
/*!
@brief Removes the port with the given name from the index
@param name The name of the port
*/
- (void)removePort:(NSString *)name;
/*!
@brief Adds the port to the index
@param port The port
@discussion The default state for the port is "not installed"
*/
- (void)setPort:(MPPort *)port;
+ (Class)classForKeyedUnarchiver;
- (Class)classForKeyedArchiver;
@end
+120
View File
@@ -0,0 +1,120 @@
/*
* $Id:$
* MacPorts.Framework
*
* Authors:
* Randall H. Wood <rhwood@macports.org>
*
* Copyright (c) 2007 Randall H. Wood <rhwood@macports.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright owner nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import "MPIndex.h"
@implementation MPIndex
- (id)init {
self = [super init];
if (self != nil) {
[self setIndex];
}
return self;
}
- (id)initWithCapacity:(unsigned)numItems {
self = [super initWithCapacity:numItems];
if (self != nil) {
[self setIndex];
}
return self;
}
- (void)dealloc {
[super dealloc];
}
/*
* We enumerate the list of ports, adding each port object to our own dictionary instead of simply copying the
* source dictionary in since we want to explicitely set the port state to uninstalled instead of the default
* state of unknown.
*
* After that we enumerate through the list of installation reciepts and set the port states for in the installed
* ports as installed, active, or outdated as appropriate
*/
- (void)setIndex {
NSDictionary *ports;
NSEnumerator *enumerator;
id port;
[[NSNotificationCenter defaultCenter] postNotificationName:MPIndexWillSetIndex object:nil];
ports = [[MPMacPorts sharedInstance] search:MPPortsAll];
enumerator = [ports keyEnumerator];
while (port = [enumerator nextObject]) {
[self setPort:[ports objectForKey:port]];
}
ports = [[MPRegistry sharedRegistry] installed];
enumerator = [ports keyEnumerator];
while (port = [enumerator nextObject]) {
[[self objectForKey:port] setStateFromReceipts:[ports objectForKey:port]];
}
[[NSNotificationCenter defaultCenter] postNotificationName:MPIndexDidSetIndex object:self];
}
- (NSArray *)ports {
return [self allValues];
}
- (NSArray *)portNames {
return [self allKeys];
}
- (MPPort *)port:(NSString *)name {
return [self objectForKey:name];
}
- (NSEnumerator *)portEnumerator {
return [self objectEnumerator];
}
- (void)removePort:(NSString *)name {
[self removeObjectForKey:name];
}
- (void)setPort:(MPPort *)port {
[port setState:MPPortStateNotInstalled];
[self setObject:port forKey:[port name]];
}
- (Class)classForKeyedArchiver {
return [MPIndex class];
}
+ (Class)classForKeyedUnarchiver {
return [MPIndex class];
}
@end
+209
View File
@@ -0,0 +1,209 @@
/*
* $Id$
* MacPorts.Framework
*
* Authors:
* Randall H. Wood <rhwood@macports.org>
*
* Copyright (c) 2007 Randall H. Wood <rhwood@macports.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright owner nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*!
@header
The MPInterpreter class allows access to a shared per-thread Tcl interpreter for
execution of MacPorts commands from upper levels in the API. This class is intended
for internal use. Framework users should not have to interact with it directly in
order to perform port operations.
*/
#import <Cocoa/Cocoa.h>
#import <Security/Security.h>
#include <tcl.h>
#import "MPNotifications.h"
//Defining some flags for MPHelperTool
#define MP_HELPER @"MPHelperTool"
#define MPPackage @"macports"
#define MPPackageVersion @"1.0"
#define TCL_RETURN_CODE @"return code"
#define TCL_RETURN_STRING @"return string"
#define MPFrameworkErrorDomain @"MacPortsFrameworkErrorDomain"
#define MPNOTIFICATION_NAME @"Notification"
#define MPCHANNEL @"Channel"
#define MPPREFIX @"Prefix"
#define MPMETHOD @"Method"
#define MPMESSAGE @"Message"
//Error codes for helper Tool
#define MPHELPINSTFAILED 0 /*Installation of helper tool failed*/
#define MPHELPUSERCANCELLED 1 /*User cancelled privileged operation.*/
#pragma mark MacPort Options
#define MPVERBOSE @"ports_verbose"
#define MPDEBUGOPTION @"ports_debug"
#define MPQUIET @"ports_quiet"
#define MPPROCESSALL @"ports_processall"
#define MPEXIT @"ports_exit"
#define MPFORCE @"ports_force"
#define MPIGNOREOLDER @"ports_ignore_older"
#define MPNODEPS @"ports_nodeps"
#define MPDODEPS @"ports_do_dependents"
#define MPSOURCEONLY @"ports_source_only"
#define MPBINARYONLY @"ports_binary_only"
#define MPAUTOCLEAN @"ports_autoclean"
#define MPTRACE @"ports_trace"
/*!
@class MPInterpreter
@abstract Tcl interpreter object
@discussion Contains a shared per-thread instance of a Tcl interpreter. The MPInterpreter class
is where the Objective-C API meets the Tcl command line. It is a per-thread interpreter to allow
users of the API to multi-thread their programs with relative ease.
*/
@interface MPInterpreter : NSObject {
Tcl_Interp* _interpreter;
NSString * helperToolInterpCommand;
NSString * helperToolCommandResult;
NSArray * defaultPortOptions;
}
+(NSString*) PKGPath;
+(void) setPKGPath:(NSString*)newPath;
+(void) terminateMPHelperTool;
+(NSTask*) task;
//Internal methods
-(BOOL) setOptionsForNewTclPort:(NSArray *)options;
-(BOOL) resetTclInterpreterWithPath:(NSString *)path;
/*!
@brief Return singleton shared MPInterpreter instance
*/
+ (MPInterpreter *)sharedInterpreter;
/*!
@brief Return singleton shared MPInterpreter instance for specified macports tcl package path
@param path An NSString specifying the absolute path for the macports tcl package
*/
+ (MPInterpreter *)sharedInterpreterWithPkgPath:(NSString *)path portOptions:(NSArray *)options;
#pragma Port Operations
#pragma Port Settings
#pragma Utilities
/*!
@brief Returns the NSString result of evaluating a Tcl expression
@param statement An NSString containing the Tcl expression
@param mportError A reference pointer to the NSError object which will be used for error handling; should not be nil.
@discussion Using the macports::getindex {source} procedure as an example we
have the following Objective-C form for calling the macports::getindex procedure:
[SomeMPInterpreterObject evaluateStringAsString:
[NSString stringWithString:@"return [macports::getindex SomeValidMacPortsSourcePath]"]];
*/
- (NSString *)evaluateStringAsString:(NSString *)statement error:(NSError **)mportError;
/*!
@brief Returns the NSString result of evaluating a Tcl expression executed as root if necessary
@param statement An NSString containing the Tcl expression
@param mportError A reference pointer to the NSError object which will be used for error handling; should not be nil.
@discussion This method is almost identical to -evaluateStringAsString. The only difference is that
it re-evaluates the Tcl expression with root privileges if the first attempt at evaluation
returns an error due to insufficient privileges. The -sync, -selfupdate and port exec methods
use this method for their operations.
[SomeMPInterpreterObject evaluateStringAsString:
[NSString stringWithString:@"return [macports::mportselfupdate]"]];
*/
- (NSString *)evaluateStringWithPossiblePrivileges:(NSString *)statement error:(NSError **)mportError;
/*!
@brief Returns an NSArray whose elements are the the elements of a Tcl list in the form of an NSString
@param list A Tcl list in the form of an NSString
@discussion This method usually takes the result of a call to the evaluateStringAsString and
evaluateArrayAsString methods which is a Tcl list and parses it into an NSArray.
*/
- (NSArray *)arrayFromTclListAsString:(NSString *)list;
/*!
@brief Returns an NSDictionary whose elements are the the elements of a Tcl list in the form of an NSString
@discussion The returned NSDictionary is of the form {k1, v1, k2, v2, ...} with ki being the keys and vi
the values in the dictionary. These keys and values are obtained from an NSString Tcl list of the
form {k1 v1 k2 v2 ...}
@param list A Tcl list in the form of an NSString
*/
- (NSDictionary *)dictionaryFromTclListAsString:(NSString *)list;
/*!
@brief Same as dictionaryFromTclListAsString method. Returns an NSMutableDictionary
rather than NSDictionary.
*/
- (NSMutableDictionary *)mutableDictionaryFromTclListAsString:(NSString *)list;
/*!
@brief Returns an NSArray whose elements are the contents of a Tcl variable
@param variable An NSString representation of a Tcl variable
*/
- (NSArray *)getVariableAsArray:(NSString *)variable;
/*!
@brief Returns an NSString representation of a Tcl variable
@param variable An NSString representtion of a Tcl variable
*/
- (NSString *)getVariableAsString:(NSString *)variable;
// METHODS FOR INTERNAL USE ONLY
- (Tcl_Interp *) sharedInternalTclInterpreter;
- (int) execute:(NSString *)pathToExecutable withArgs:(NSArray*)args;
- (void)setAuthorizationRef:(AuthorizationRef)authRef;
- (BOOL)checkIfAuthorized;
-(NSString *)evaluateStringWithMPHelperTool:(NSString *)statement error:(NSError **)mportError;
-(NSString *)evaluateStringWithMPPortProcess:(NSString *)statement error:(NSError **)mportError;
@end
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
/*
* $Id$
* MacPorts.Framework
*
* Authors:
* Randall H. Wood <rhwood@macports.org>
*
* Copyright (c) 2007 Randall H. Wood <rhwood@macports.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright owner nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import <SenTestingKit/SenTestingKit.h>
#import "MPInterpreter.h"
@interface MPInterpreterTest : SenTestCase {
MPInterpreter * interp;
}
- (void)testInitialization;
- (void)testGetVariableAsArray;
//- (void)testEvaluateStringAsString;
//- (void)testGetVariableAsString;
@end

Some files were not shown because too many files have changed in this diff Show More