mirror of
https://github.com/macports/pallet.git
synced 2026-07-12 18:18:47 -07:00
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:
+2489
File diff suppressed because it is too large
Load Diff
+790
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.
@@ -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>
|
||||
@@ -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
|
||||
}
|
||||
|
||||
};
|
||||
@@ -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
|
||||
+574
File diff suppressed because it is too large
Load Diff
+119
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user