/* * BRLTTY - A background process providing access to the console screen (when in * text mode) for a blind person using a refreshable braille display. * * Copyright (C) 1995-2019 by The BRLTTY Developers. * * BRLTTY comes with ABSOLUTELY NO WARRANTY. * * This is free software, placed under the terms of the * GNU Lesser General Public License, as published by the Free Software * Foundation; either version 2.1 of the License, or (at your option) any * later version. Please see the file LICENSE-LGPL for details. * * Web Page: http://brltty.app/ * * This software is maintained by Dave Mielke . */ #include "prologue.h" #include #include #import #import #import #include "log.h" #include "system.h" #include "system_darwin.h" static inline CFRunLoopRef getRunLoop (void) { return CFRunLoopGetCurrent(); } static inline CFStringRef getRunMode (void) { return kCFRunLoopDefaultMode; } IOReturn executeRunLoop (int seconds) { return CFRunLoopRunInMode(getRunMode(), seconds, 1); } void addRunLoopSource (CFRunLoopSourceRef source) { CFRunLoopAddSource(getRunLoop(), source, getRunMode()); } void removeRunLoopSource (CFRunLoopSourceRef source) { CFRunLoopRemoveSource(getRunLoop(), source, getRunMode()); } void setDarwinSystemError (IOReturn result) { switch (result) { default: errno = EIO; break; //MAP_DARWIN_ERROR(KERN_SUCCESS, ) MAP_DARWIN_ERROR(KERN_INVALID_ADDRESS, EINVAL) MAP_DARWIN_ERROR(KERN_PROTECTION_FAILURE, EFAULT) MAP_DARWIN_ERROR(KERN_NO_SPACE, ENOSPC) MAP_DARWIN_ERROR(KERN_INVALID_ARGUMENT, EINVAL) //MAP_DARWIN_ERROR(KERN_FAILURE, ) MAP_DARWIN_ERROR(KERN_RESOURCE_SHORTAGE, EAGAIN) //MAP_DARWIN_ERROR(KERN_NOT_RECEIVER, ) MAP_DARWIN_ERROR(KERN_NO_ACCESS, EACCES) MAP_DARWIN_ERROR(KERN_MEMORY_FAILURE, EFAULT) MAP_DARWIN_ERROR(KERN_MEMORY_ERROR, EFAULT) //MAP_DARWIN_ERROR(KERN_ALREADY_IN_SET, ) //MAP_DARWIN_ERROR(KERN_NOT_IN_SET, ) MAP_DARWIN_ERROR(KERN_NAME_EXISTS, EEXIST) MAP_DARWIN_ERROR(KERN_ABORTED, ECANCELED) MAP_DARWIN_ERROR(KERN_INVALID_NAME, EINVAL) MAP_DARWIN_ERROR(KERN_INVALID_TASK, EINVAL) MAP_DARWIN_ERROR(KERN_INVALID_RIGHT, EINVAL) MAP_DARWIN_ERROR(KERN_INVALID_VALUE, EINVAL) //MAP_DARWIN_ERROR(KERN_UREFS_OVERFLOW, ) MAP_DARWIN_ERROR(KERN_INVALID_CAPABILITY, EINVAL) //MAP_DARWIN_ERROR(KERN_RIGHT_EXISTS, ) MAP_DARWIN_ERROR(KERN_INVALID_HOST, EINVAL) //MAP_DARWIN_ERROR(KERN_MEMORY_PRESENT, ) //MAP_DARWIN_ERROR(KERN_MEMORY_DATA_MOVED, ) //MAP_DARWIN_ERROR(KERN_MEMORY_RESTART_COPY, ) MAP_DARWIN_ERROR(KERN_INVALID_PROCESSOR_SET, EINVAL) //MAP_DARWIN_ERROR(KERN_POLICY_LIMIT, ) MAP_DARWIN_ERROR(KERN_INVALID_POLICY, EINVAL) MAP_DARWIN_ERROR(KERN_INVALID_OBJECT, EINVAL) //MAP_DARWIN_ERROR(KERN_ALREADY_WAITING, ) //MAP_DARWIN_ERROR(KERN_DEFAULT_SET, ) //MAP_DARWIN_ERROR(KERN_EXCEPTION_PROTECTED, ) MAP_DARWIN_ERROR(KERN_INVALID_LEDGER, EINVAL) MAP_DARWIN_ERROR(KERN_INVALID_MEMORY_CONTROL, EINVAL) MAP_DARWIN_ERROR(KERN_INVALID_SECURITY, EINVAL) //MAP_DARWIN_ERROR(KERN_NOT_DEPRESSED, ) //MAP_DARWIN_ERROR(KERN_TERMINATED, ) //MAP_DARWIN_ERROR(KERN_LOCK_SET_DESTROYED, ) //MAP_DARWIN_ERROR(KERN_LOCK_UNSTABLE, ) //MAP_DARWIN_ERROR(KERN_LOCK_OWNED, ) //MAP_DARWIN_ERROR(KERN_LOCK_OWNED_SELF, ) //MAP_DARWIN_ERROR(KERN_SEMAPHORE_DESTROYED, ) //MAP_DARWIN_ERROR(KERN_RPC_SERVER_TERMINATED, ) //MAP_DARWIN_ERROR(KERN_RPC_TERMINATE_ORPHAN, ) //MAP_DARWIN_ERROR(KERN_RPC_CONTINUE_ORPHAN, ) MAP_DARWIN_ERROR(KERN_NOT_SUPPORTED, ENOTSUP) MAP_DARWIN_ERROR(KERN_NODE_DOWN, EHOSTDOWN) //MAP_DARWIN_ERROR(KERN_NOT_WAITING, ) MAP_DARWIN_ERROR(KERN_OPERATION_TIMED_OUT, ETIMEDOUT) MAP_DARWIN_ERROR(kIOReturnSuccess, 0) //MAP_DARWIN_ERROR(kIOReturnError, ) MAP_DARWIN_ERROR(kIOReturnNoMemory, ENOMEM) MAP_DARWIN_ERROR(kIOReturnNoResources, EAGAIN) //MAP_DARWIN_ERROR(kIOReturnIPCError, ) MAP_DARWIN_ERROR(kIOReturnNoDevice, ENODEV) MAP_DARWIN_ERROR(kIOReturnNotPrivileged, EACCES) MAP_DARWIN_ERROR(kIOReturnBadArgument, EINVAL) MAP_DARWIN_ERROR(kIOReturnLockedRead, ENOLCK) MAP_DARWIN_ERROR(kIOReturnLockedWrite, ENOLCK) MAP_DARWIN_ERROR(kIOReturnExclusiveAccess, EBUSY) //MAP_DARWIN_ERROR(kIOReturnBadMessageID, ) MAP_DARWIN_ERROR(kIOReturnUnsupported, ENOTSUP) //MAP_DARWIN_ERROR(kIOReturnVMError, ) //MAP_DARWIN_ERROR(kIOReturnInternalError, ) MAP_DARWIN_ERROR(kIOReturnIOError, EIO) MAP_DARWIN_ERROR(kIOReturnCannotLock, ENOLCK) MAP_DARWIN_ERROR(kIOReturnNotOpen, EBADF) MAP_DARWIN_ERROR(kIOReturnNotReadable, EACCES) MAP_DARWIN_ERROR(kIOReturnNotWritable, EROFS) //MAP_DARWIN_ERROR(kIOReturnNotAligned, ) MAP_DARWIN_ERROR(kIOReturnBadMedia, ENXIO) //MAP_DARWIN_ERROR(kIOReturnStillOpen, ) //MAP_DARWIN_ERROR(kIOReturnRLDError, ) MAP_DARWIN_ERROR(kIOReturnDMAError, EDEVERR) MAP_DARWIN_ERROR(kIOReturnBusy, EBUSY) MAP_DARWIN_ERROR(kIOReturnTimeout, ETIMEDOUT) MAP_DARWIN_ERROR(kIOReturnOffline, ENXIO) MAP_DARWIN_ERROR(kIOReturnNotReady, ENXIO) MAP_DARWIN_ERROR(kIOReturnNotAttached, ENXIO) MAP_DARWIN_ERROR(kIOReturnNoChannels, EDEVERR) MAP_DARWIN_ERROR(kIOReturnNoSpace, ENOSPC) MAP_DARWIN_ERROR(kIOReturnPortExists, EADDRINUSE) MAP_DARWIN_ERROR(kIOReturnCannotWire, ENOMEM) //MAP_DARWIN_ERROR(kIOReturnNoInterrupt, ) MAP_DARWIN_ERROR(kIOReturnNoFrames, EDEVERR) MAP_DARWIN_ERROR(kIOReturnMessageTooLarge, EMSGSIZE) MAP_DARWIN_ERROR(kIOReturnNotPermitted, EPERM) MAP_DARWIN_ERROR(kIOReturnNoPower, EPWROFF) MAP_DARWIN_ERROR(kIOReturnNoMedia, ENXIO) MAP_DARWIN_ERROR(kIOReturnUnformattedMedia, ENXIO) MAP_DARWIN_ERROR(kIOReturnUnsupportedMode, ENOSYS) MAP_DARWIN_ERROR(kIOReturnUnderrun, EDEVERR) MAP_DARWIN_ERROR(kIOReturnOverrun, EDEVERR) MAP_DARWIN_ERROR(kIOReturnDeviceError, EDEVERR) //MAP_DARWIN_ERROR(kIOReturnNoCompletion, ) MAP_DARWIN_ERROR(kIOReturnAborted, ECANCELED) MAP_DARWIN_ERROR(kIOReturnNoBandwidth, EDEVERR) MAP_DARWIN_ERROR(kIOReturnNotResponding, EDEVERR) MAP_DARWIN_ERROR(kIOReturnIsoTooOld, EDEVERR) MAP_DARWIN_ERROR(kIOReturnIsoTooNew, EDEVERR) MAP_DARWIN_ERROR(kIOReturnNotFound, ENOENT) //MAP_DARWIN_ERROR(kIOReturnInvalid, ) } } void initializeSystemObject (void) { } @interface AsynchronousResult () @property (assign, readwrite) int isFinished; @property (assign, readwrite) IOReturn finalStatus; @end @implementation AsynchronousResult @synthesize isFinished; @synthesize finalStatus; - (int) wait : (int) timeout { if (self.isFinished) return 1; while (1) { IOReturn result = executeRunLoop(timeout); if (self.isFinished) return 1; if (result == kCFRunLoopRunHandledSource) continue; if (result == kCFRunLoopRunTimedOut) return 0; } } - (void) setStatus : (IOReturn) status { self.finalStatus = status; self.isFinished = 1; } @end @interface AsynchronousTask () @property (assign, readwrite) NSThread *taskThread; @property (assign, readwrite) CFRunLoopRef taskRunLoop; @property (retain) NSCondition *startSynchronizer; @property (retain) NSThread *resultThread; - (void) taskFinished; - (void) main; - (void) endTask; @end @implementation AsynchronousTask @synthesize taskThread; @synthesize taskRunLoop; @synthesize startSynchronizer; @synthesize resultThread; - (IOReturn) run { logMessage(LOG_WARNING, "run method not overridden"); return kIOReturnSuccess; } - (void) taskFinished { self.resultThread = nil; } - (void) main { NSAutoreleasePool *pool = [NSAutoreleasePool new]; [self.startSynchronizer lock]; self.taskThread = [NSThread currentThread]; self.taskRunLoop = CFRunLoopGetCurrent(); [self.startSynchronizer signal]; [self.startSynchronizer unlock]; [self setStatus:[self run]]; [self performSelector:@selector(taskFinished) onThread:self.resultThread withObject:nil waitUntilDone:0]; self.taskThread = nil; [pool drain]; } - (int) start { if ((self.startSynchronizer = [NSCondition new])) { self.resultThread = [NSThread currentThread]; [self.startSynchronizer lock]; [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]; [self.startSynchronizer wait]; [self.startSynchronizer unlock]; self.startSynchronizer = nil; return 1; } return 0; } - (void) endTask { CFRunLoopStop(self.taskRunLoop); } - (void) stop { [self performSelector:@selector(endTask) onThread:self.taskThread withObject:nil waitUntilDone:0]; } @end