2010-02-25 08:36:34 +00:00
|
|
|
|
/* Copyright (C) 1998 Free Software Foundation, Inc.
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
|
|
|
|
Created: October 1998
|
|
|
|
|
|
1999-02-04 13:06:58 +00:00
|
|
|
|
This file is part of the GNUstep Project
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
2008-06-08 10:38:33 +00:00
|
|
|
|
This program is free software; you can redistribute it and/or
|
1999-02-04 13:06:58 +00:00
|
|
|
|
modify it under the terms of the GNU General Public License
|
2008-06-08 10:38:33 +00:00
|
|
|
|
as published by the Free Software Foundation; either
|
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public
|
2008-06-08 10:38:33 +00:00
|
|
|
|
License along with this program; see the file COPYING.
|
1999-02-04 13:06:58 +00:00
|
|
|
|
If not, write to the Free Software Foundation,
|
2024-11-07 13:37:59 +00:00
|
|
|
|
31 Milk Street #960789 Boston, MA 02196 USA.
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
2010-02-25 08:36:34 +00:00
|
|
|
|
#import "common.h"
|
|
|
|
|
|
2010-02-19 14:21:02 +00:00
|
|
|
|
#include <stdio.h>
|
2021-01-18 13:20:14 +00:00
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#include <io.h>
|
|
|
|
|
#endif
|
2010-02-19 14:21:02 +00:00
|
|
|
|
|
2010-02-14 14:30:02 +00:00
|
|
|
|
#import "Foundation/NSArray.h"
|
|
|
|
|
#import "Foundation/NSAutoreleasePool.h"
|
|
|
|
|
#import "Foundation/NSBundle.h"
|
|
|
|
|
#import "Foundation/NSConnection.h"
|
2010-02-15 14:42:00 +00:00
|
|
|
|
#import "Foundation/NSData.h"
|
2010-02-14 14:30:02 +00:00
|
|
|
|
#import "Foundation/NSDistantObject.h"
|
|
|
|
|
#import "Foundation/NSDistributedNotificationCenter.h"
|
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
|
#import "Foundation/NSHashTable.h"
|
|
|
|
|
#import "Foundation/NSHost.h"
|
|
|
|
|
#import "Foundation/NSNotification.h"
|
|
|
|
|
#import "Foundation/NSPort.h"
|
|
|
|
|
#import "Foundation/NSPortNameServer.h"
|
|
|
|
|
#import "Foundation/NSProcessInfo.h"
|
|
|
|
|
#import "Foundation/NSRunLoop.h"
|
|
|
|
|
#import "Foundation/NSTask.h"
|
2016-06-24 10:44:40 +00:00
|
|
|
|
#import "Foundation/NSTimer.h"
|
2010-02-14 14:30:02 +00:00
|
|
|
|
#import "Foundation/NSUserDefaults.h"
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
1999-06-24 19:30:29 +00:00
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#if defined(__MINGW__)
|
2002-03-20 12:59:45 +00:00
|
|
|
|
#include "process.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-12-15 09:42:39 +00:00
|
|
|
|
|
|
|
|
|
#if defined(HAVE_SYS_FCNTL_H)
|
|
|
|
|
# include <sys/fcntl.h>
|
|
|
|
|
#elif defined(HAVE_FCNTL_H)
|
|
|
|
|
# include <fcntl.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-09-01 00:46:26 +00:00
|
|
|
|
#ifdef HAVE_SYSLOG_H
|
|
|
|
|
#include <syslog.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-12-15 09:42:39 +00:00
|
|
|
|
#if defined(HAVE_SYS_SIGNAL_H)
|
|
|
|
|
# include <sys/signal.h>
|
|
|
|
|
#elif defined(HAVE_SIGNAL_H)
|
|
|
|
|
# include <signal.h>
|
|
|
|
|
#endif
|
2003-05-13 05:24:32 +00:00
|
|
|
|
|
|
|
|
|
#ifndef NSIG
|
|
|
|
|
#define NSIG 32
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-11-27 15:01:19 +00:00
|
|
|
|
static BOOL debugging = NO;
|
2005-02-08 11:57:39 +00:00
|
|
|
|
static BOOL is_daemon = NO; /* Currently running as daemon. */
|
2007-03-06 18:38:22 +00:00
|
|
|
|
static BOOL auto_stop = NO; /* Should we shut down when unused? */
|
2003-09-01 00:46:26 +00:00
|
|
|
|
|
2016-06-24 10:44:40 +00:00
|
|
|
|
static NSTimer *timer = nil; /* When to shut down. */
|
|
|
|
|
|
2012-08-26 08:55:49 +00:00
|
|
|
|
#if defined(HAVE_SYSLOG) || defined(HAVE_SLOGF)
|
|
|
|
|
# if defined(HAVE_SLOGF)
|
|
|
|
|
# include <sys/slogcodes.h>
|
|
|
|
|
# include <sys/slog.h>
|
|
|
|
|
# define LOG_CRIT _SLOG_CRITICAL
|
|
|
|
|
# define LOG_DEBUG _SLOG_DEBUG1
|
|
|
|
|
# define LOG_ERR _SLOG_ERROR
|
|
|
|
|
# define LOG_INFO _SLOG_INFO
|
|
|
|
|
# define LOG_WARNING _SLOG_WARNING
|
|
|
|
|
# define syslog(prio, msg,...) slogf(_SLOG_SETCODE(_SLOG_SYSLOG, 0), prio, msg, __VA_ARGS__)
|
|
|
|
|
# endif
|
2007-03-06 21:42:26 +00:00
|
|
|
|
static int log_priority = LOG_DEBUG;
|
2003-09-01 00:46:26 +00:00
|
|
|
|
|
|
|
|
|
static void
|
2009-01-25 08:41:30 +00:00
|
|
|
|
gdnc_log (int prio, const char *ebuf)
|
2003-09-01 00:46:26 +00:00
|
|
|
|
{
|
|
|
|
|
if (is_daemon)
|
|
|
|
|
{
|
2012-08-26 08:55:49 +00:00
|
|
|
|
# if defined(HAVE_SLOGF)
|
|
|
|
|
// Let's not have 0 as the value for prio. It means "shutdown" on QNX
|
|
|
|
|
syslog (prio ? prio : log_priority, "%s", ebuf);
|
|
|
|
|
# else
|
2010-01-10 14:38:16 +00:00
|
|
|
|
syslog (log_priority | prio, "%s", ebuf);
|
2012-08-26 08:55:49 +00:00
|
|
|
|
# endif
|
2003-09-01 00:46:26 +00:00
|
|
|
|
}
|
|
|
|
|
else if (prio == LOG_INFO)
|
|
|
|
|
{
|
2023-10-09 19:02:35 +00:00
|
|
|
|
fprintf (stdout, "%s\n", ebuf);
|
|
|
|
|
fflush (stdout);
|
2003-09-01 00:46:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-10-09 19:02:35 +00:00
|
|
|
|
fprintf (stderr, "%s\n", ebuf);
|
|
|
|
|
fflush (stderr);
|
2003-09-01 00:46:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (prio == LOG_CRIT)
|
|
|
|
|
{
|
|
|
|
|
if (is_daemon)
|
|
|
|
|
{
|
2012-08-26 08:55:49 +00:00
|
|
|
|
syslog (LOG_CRIT, "%s", "exiting.");
|
2003-09-01 00:46:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr, "exiting.\n");
|
|
|
|
|
fflush (stderr);
|
|
|
|
|
}
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-08-26 08:55:49 +00:00
|
|
|
|
|
2003-09-01 00:46:26 +00:00
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
#define LOG_CRIT 2
|
|
|
|
|
#define LOG_DEBUG 0
|
|
|
|
|
#define LOG_ERR 1
|
|
|
|
|
#define LOG_INFO 0
|
|
|
|
|
#define LOG_WARNING 0
|
2009-01-25 08:41:30 +00:00
|
|
|
|
static void
|
|
|
|
|
gdnc_log (int prio, const char *ebuf)
|
2003-09-01 00:46:26 +00:00
|
|
|
|
{
|
|
|
|
|
write (2, ebuf, strlen (ebuf));
|
|
|
|
|
write (2, "\n", 1);
|
|
|
|
|
if (prio == LOG_CRIT)
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr, "exiting.\n");
|
|
|
|
|
fflush (stderr);
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-05-13 05:24:32 +00:00
|
|
|
|
static void
|
|
|
|
|
ihandler(int sig)
|
|
|
|
|
{
|
2003-05-13 16:00:21 +00:00
|
|
|
|
static BOOL beenHere = NO;
|
|
|
|
|
BOOL action;
|
2005-11-15 11:25:31 +00:00
|
|
|
|
NSString *e;
|
2003-05-13 05:24:32 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2003-05-13 16:00:21 +00:00
|
|
|
|
* Deal with recursive call of handler.
|
2003-05-13 05:24:32 +00:00
|
|
|
|
*/
|
2003-05-13 16:00:21 +00:00
|
|
|
|
if (beenHere == YES)
|
2003-05-13 05:24:32 +00:00
|
|
|
|
{
|
2003-05-13 16:00:21 +00:00
|
|
|
|
abort();
|
2003-05-13 05:24:32 +00:00
|
|
|
|
}
|
2003-05-13 16:00:21 +00:00
|
|
|
|
beenHere = YES;
|
|
|
|
|
|
2003-05-13 05:24:32 +00:00
|
|
|
|
/*
|
|
|
|
|
* If asked to terminate, do so cleanly.
|
|
|
|
|
*/
|
|
|
|
|
if (sig == SIGTERM)
|
|
|
|
|
{
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
2003-05-13 06:02:00 +00:00
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2003-05-13 16:00:21 +00:00
|
|
|
|
action = YES; // abort() by default.
|
2003-05-13 06:02:00 +00:00
|
|
|
|
#else
|
2003-05-13 16:00:21 +00:00
|
|
|
|
action = NO; // exit() by default.
|
2003-05-13 06:02:00 +00:00
|
|
|
|
#endif
|
2005-11-15 11:25:31 +00:00
|
|
|
|
e = [[[NSProcessInfo processInfo] environment] objectForKey:
|
|
|
|
|
@"CRASH_ON_ABORT"];
|
|
|
|
|
if (e != nil)
|
2003-05-13 06:02:00 +00:00
|
|
|
|
{
|
2005-11-15 11:25:31 +00:00
|
|
|
|
action = [e boolValue];
|
2003-05-13 06:02:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-05-13 16:00:21 +00:00
|
|
|
|
if (action == YES)
|
2003-05-13 06:02:00 +00:00
|
|
|
|
{
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2003-05-13 16:00:21 +00:00
|
|
|
|
fprintf(stderr, "gdnc killed by signal %d\n", sig);
|
2003-05-13 06:02:00 +00:00
|
|
|
|
exit(sig);
|
|
|
|
|
}
|
2003-05-13 05:24:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
#include "gdnc.h"
|
|
|
|
|
|
2003-07-04 16:27:02 +00:00
|
|
|
|
/*
|
|
|
|
|
* The following dummy class is here solely as a workaround for pre 3.3
|
|
|
|
|
* versions of gcc where protocols didn't work properly unless implemented
|
2003-07-04 16:50:30 +00:00
|
|
|
|
* in the source where the '@protocol()' directive is used.
|
2003-07-04 16:27:02 +00:00
|
|
|
|
*/
|
2004-12-28 08:35:36 +00:00
|
|
|
|
@interface NSDistributedNotificationCenterGDNCDummy : NSObject <GDNCClient>
|
2003-07-04 16:27:02 +00:00
|
|
|
|
- (oneway void) postNotificationName: (NSString*)name
|
|
|
|
|
object: (NSString*)object
|
|
|
|
|
userInfo: (NSData*)info
|
|
|
|
|
selector: (NSString*)aSelector
|
2009-02-23 20:42:32 +00:00
|
|
|
|
to: (uint64_t)observer;
|
2003-07-04 16:27:02 +00:00
|
|
|
|
@end
|
2004-12-28 08:35:36 +00:00
|
|
|
|
@implementation NSDistributedNotificationCenterGDNCDummy
|
2003-07-04 16:27:02 +00:00
|
|
|
|
- (oneway void) postNotificationName: (NSString*)name
|
|
|
|
|
object: (NSString*)object
|
|
|
|
|
userInfo: (NSData*)info
|
|
|
|
|
selector: (NSString*)aSelector
|
2009-02-23 20:42:32 +00:00
|
|
|
|
to: (uint64_t)observer
|
2003-07-04 16:27:02 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
return;
|
2003-07-04 16:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
@interface GDNCNotification : NSObject
|
|
|
|
|
{
|
|
|
|
|
@public
|
|
|
|
|
NSString *name;
|
|
|
|
|
NSString *object;
|
|
|
|
|
NSData *info;
|
|
|
|
|
}
|
|
|
|
|
+ (GDNCNotification*) notificationWithName: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)notificationObject
|
|
|
|
|
data: (NSData*)notificationData;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GDNCNotification
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(name);
|
|
|
|
|
RELEASE(object);
|
|
|
|
|
RELEASE(info);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
2008-11-27 15:01:19 +00:00
|
|
|
|
- (NSString*) description
|
|
|
|
|
{
|
|
|
|
|
return [NSString stringWithFormat: @"%@ Name:'%@' Object:'%@' Info:'%@'",
|
|
|
|
|
[super description], name, object, info];
|
|
|
|
|
}
|
1998-11-02 16:59:57 +00:00
|
|
|
|
+ (GDNCNotification*) notificationWithName: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)notificationObject
|
|
|
|
|
data: (NSData*)notificationData
|
|
|
|
|
{
|
|
|
|
|
GDNCNotification *tmp = [GDNCNotification alloc];
|
|
|
|
|
|
2000-07-03 13:18:07 +00:00
|
|
|
|
tmp->name = RETAIN(notificationName);
|
|
|
|
|
tmp->object = RETAIN(notificationObject);
|
|
|
|
|
tmp->info = RETAIN(notificationData);
|
|
|
|
|
return AUTORELEASE(tmp);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Information about a notification observer.
|
|
|
|
|
*/
|
|
|
|
|
@interface GDNCClient : NSObject
|
|
|
|
|
{
|
|
|
|
|
@public
|
|
|
|
|
BOOL suspended;
|
|
|
|
|
id <GDNCClient> client;
|
|
|
|
|
NSMutableArray *observers;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GDNCClient
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(observers);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
|
{
|
|
|
|
|
observers = [NSMutableArray new];
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Information about a notification observer.
|
|
|
|
|
*/
|
|
|
|
|
@interface GDNCObserver : NSObject
|
|
|
|
|
{
|
|
|
|
|
@public
|
2009-02-23 20:42:32 +00:00
|
|
|
|
uint64_t observer;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
NSString *notificationName;
|
|
|
|
|
NSString *notificationObject;
|
1998-11-09 11:05:37 +00:00
|
|
|
|
NSString *selector;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
GDNCClient *client;
|
|
|
|
|
NSMutableArray *queue;
|
|
|
|
|
NSNotificationSuspensionBehavior behavior;
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GDNCObserver
|
|
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(queue);
|
|
|
|
|
RELEASE(selector);
|
|
|
|
|
RELEASE(notificationName);
|
|
|
|
|
RELEASE(notificationObject);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
|
{
|
|
|
|
|
queue = [[NSMutableArray alloc] initWithCapacity: 1];
|
1998-11-09 11:05:37 +00:00
|
|
|
|
return self;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@interface GDNCServer : NSObject <GDNCProtocol>
|
|
|
|
|
{
|
|
|
|
|
NSConnection *conn;
|
|
|
|
|
NSMapTable *connections;
|
|
|
|
|
NSHashTable *allObservers;
|
|
|
|
|
NSMutableDictionary *observersForNames;
|
|
|
|
|
NSMutableDictionary *observersForObjects;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) addObserver: (uint64_t)anObserver
|
1998-11-09 11:05:37 +00:00
|
|
|
|
selector: (NSString*)aSelector
|
2004-03-29 03:37:46 +00:00
|
|
|
|
name: (NSString*)notificationName
|
1998-11-02 16:59:57 +00:00
|
|
|
|
object: (NSString*)anObject
|
|
|
|
|
suspensionBehavior: (NSNotificationSuspensionBehavior)suspensionBehavior
|
|
|
|
|
for: (id<GDNCClient>)client;
|
|
|
|
|
|
2000-07-03 13:18:07 +00:00
|
|
|
|
- (BOOL) connection: (NSConnection*)ancestor
|
|
|
|
|
shouldMakeNewConnection: (NSConnection*)newConn;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
- (id) connectionBecameInvalid: (NSNotification*)notification;
|
|
|
|
|
|
2009-11-27 13:05:26 +00:00
|
|
|
|
- (oneway void) postNotificationName: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)notificationObject
|
|
|
|
|
userInfo: (NSData*)d
|
|
|
|
|
deliverImmediately: (BOOL)deliverImmediately
|
|
|
|
|
for: (id<GDNCClient>)client;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
- (void) removeObserver: (GDNCObserver*)observer;
|
|
|
|
|
|
|
|
|
|
- (void) removeObserversForClients: (NSMapTable*)clients;
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) removeObserver: (uint64_t)anObserver
|
2004-03-29 03:37:46 +00:00
|
|
|
|
name: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)notificationObject
|
1998-11-02 16:59:57 +00:00
|
|
|
|
for: (id<GDNCClient>)client;
|
|
|
|
|
|
|
|
|
|
- (void) setSuspended: (BOOL)flag
|
|
|
|
|
for: (id<GDNCClient>)client;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation GDNCServer
|
|
|
|
|
|
2016-06-24 10:44:40 +00:00
|
|
|
|
- (void) autoStop: (NSTimer*)t
|
|
|
|
|
{
|
|
|
|
|
if (t == timer)
|
|
|
|
|
{
|
|
|
|
|
timer = nil;
|
|
|
|
|
}
|
|
|
|
|
if (auto_stop == YES && NSCountMapTable(connections) == 0)
|
|
|
|
|
{
|
|
|
|
|
/* There is nothing else using this process, stop.
|
|
|
|
|
*/
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
1999-06-17 10:53:24 +00:00
|
|
|
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
NSMapEnumerator enumerator;
|
|
|
|
|
NSConnection *connection;
|
|
|
|
|
NSMapTable *clients;
|
|
|
|
|
|
|
|
|
|
if (conn)
|
|
|
|
|
{
|
1999-06-17 10:53:24 +00:00
|
|
|
|
[nc removeObserver: self
|
|
|
|
|
name: NSConnectionDidDieNotification
|
|
|
|
|
object: conn];
|
2000-07-03 13:18:07 +00:00
|
|
|
|
DESTROY(conn);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Free all the client map tables in the connections map table and
|
|
|
|
|
* ignore notifications from those connections.
|
|
|
|
|
*/
|
|
|
|
|
enumerator = NSEnumerateMapTable(connections);
|
|
|
|
|
while (NSNextMapEnumeratorPair(&enumerator,
|
|
|
|
|
(void**)&connection, (void**)&clients) == YES)
|
|
|
|
|
{
|
1999-06-17 10:53:24 +00:00
|
|
|
|
[nc removeObserver: self
|
|
|
|
|
name: NSConnectionDidDieNotification
|
|
|
|
|
object: connection];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[self removeObserversForClients: clients];
|
|
|
|
|
NSFreeMapTable(clients);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2004-06-22 22:52:44 +00:00
|
|
|
|
* Now free the connections map itself and the table of observers.
|
1998-11-02 16:59:57 +00:00
|
|
|
|
*/
|
|
|
|
|
NSFreeMapTable(connections);
|
|
|
|
|
NSFreeHashTable(allObservers);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* And release the maps of notification names and objects.
|
|
|
|
|
*/
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(observersForNames);
|
|
|
|
|
RELEASE(observersForObjects);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
|
{
|
2005-04-12 09:48:04 +00:00
|
|
|
|
NSString *hostname;
|
|
|
|
|
NSString *service;
|
|
|
|
|
BOOL isNetwork = NO;
|
|
|
|
|
BOOL isPublic = NO;
|
|
|
|
|
NSPort *port;
|
|
|
|
|
NSPortNameServer *ns;
|
|
|
|
|
NSUserDefaults *defs;
|
2002-03-09 18:21:20 +00:00
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
connections = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
|
|
|
|
NSNonOwnedPointerMapValueCallBacks, 0);
|
|
|
|
|
allObservers = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0);
|
|
|
|
|
observersForNames = [NSMutableDictionary new];
|
|
|
|
|
observersForObjects = [NSMutableDictionary new];
|
2002-03-09 18:21:20 +00:00
|
|
|
|
|
2005-04-12 09:48:04 +00:00
|
|
|
|
defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
hostname = [defs stringForKey: @"NSHost"];
|
|
|
|
|
if ([hostname length] > 0 || [defs boolForKey: @"GSPublic"] == YES)
|
2002-12-12 15:14:13 +00:00
|
|
|
|
{
|
2005-04-12 09:48:04 +00:00
|
|
|
|
if (hostname == nil || [hostname isEqualToString: @"localhost"] == YES
|
|
|
|
|
|| [hostname isEqualToString: @"127.0.0.1"] == YES)
|
|
|
|
|
{
|
|
|
|
|
hostname = @"";
|
|
|
|
|
}
|
|
|
|
|
isPublic = YES;
|
2002-12-12 15:14:13 +00:00
|
|
|
|
}
|
2005-04-12 09:48:04 +00:00
|
|
|
|
else if ([defs boolForKey: @"GSNetwork"] == YES)
|
2003-07-15 04:22:59 +00:00
|
|
|
|
{
|
2005-04-12 09:48:04 +00:00
|
|
|
|
isNetwork = YES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isNetwork)
|
2003-07-15 04:22:59 +00:00
|
|
|
|
{
|
2005-04-12 09:48:04 +00:00
|
|
|
|
service = GDNC_NETWORK;
|
|
|
|
|
ns = [NSSocketPortNameServer sharedInstance];
|
|
|
|
|
port = (NSPort*)[NSSocketPort port];
|
|
|
|
|
}
|
|
|
|
|
else if (isPublic)
|
|
|
|
|
{
|
|
|
|
|
service = GDNC_SERVICE;
|
|
|
|
|
ns = [NSSocketPortNameServer sharedInstance];
|
2018-02-05 13:21:15 +00:00
|
|
|
|
port = (NSPort*)[NSSocketPort port];
|
2003-07-15 04:22:59 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-11-22 06:30:51 +00:00
|
|
|
|
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
|
|
|
|
|
if ([defs objectForKey: @"NSPortIsMessagePort"] != nil
|
|
|
|
|
&& [defs boolForKey: @"NSPortIsMessagePort"] == NO)
|
|
|
|
|
{
|
|
|
|
|
ns = [NSSocketPortNameServer sharedInstance];
|
|
|
|
|
port = (NSPort*)[NSSocketPort port];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ns = [NSMessagePortNameServer sharedInstance];
|
|
|
|
|
port = (NSPort*)[NSMessagePort port];
|
|
|
|
|
}
|
2005-04-12 09:48:04 +00:00
|
|
|
|
hostname = @"";
|
|
|
|
|
service = GDNC_SERVICE;
|
2003-07-15 04:22:59 +00:00
|
|
|
|
}
|
2005-04-12 09:48:04 +00:00
|
|
|
|
|
|
|
|
|
conn = [[NSConnection alloc] initWithReceivePort: port sendPort: nil];
|
2003-07-15 04:22:59 +00:00
|
|
|
|
[conn setRootObject: self];
|
|
|
|
|
|
2005-04-12 09:48:04 +00:00
|
|
|
|
if ([hostname length] == 0
|
2002-12-12 15:14:13 +00:00
|
|
|
|
|| [[NSHost hostWithName: hostname] isEqual: [NSHost currentHost]] == YES)
|
2002-03-09 18:21:20 +00:00
|
|
|
|
{
|
2005-04-12 09:48:04 +00:00
|
|
|
|
if ([conn registerName: service withNameServer: ns] == NO)
|
2002-03-09 18:21:20 +00:00
|
|
|
|
{
|
2023-08-01 15:37:22 +00:00
|
|
|
|
NSLog(@"gdnc - unable to register with name server as %@ - quitting.",
|
2002-12-12 15:14:13 +00:00
|
|
|
|
service);
|
2002-03-09 18:21:20 +00:00
|
|
|
|
DESTROY(self);
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
2002-03-09 18:21:20 +00:00
|
|
|
|
NSHost *host = [NSHost hostWithName: hostname];
|
|
|
|
|
NSPort *port = [conn receivePort];
|
|
|
|
|
NSArray *a;
|
|
|
|
|
unsigned c;
|
|
|
|
|
|
|
|
|
|
if (host == nil)
|
|
|
|
|
{
|
2023-08-01 15:37:22 +00:00
|
|
|
|
NSLog(@"gdnc - unknown NSHost argument ... %@ - quitting.", hostname);
|
2002-03-09 18:21:20 +00:00
|
|
|
|
DESTROY(self);
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
a = [host names];
|
|
|
|
|
c = [a count];
|
|
|
|
|
while (c-- > 0)
|
|
|
|
|
{
|
|
|
|
|
NSString *name = [a objectAtIndex: c];
|
|
|
|
|
|
2002-12-12 15:14:13 +00:00
|
|
|
|
name = [service stringByAppendingFormat: @"-%@", name];
|
2002-03-09 18:21:20 +00:00
|
|
|
|
if ([ns registerPort: port forName: name] == NO)
|
|
|
|
|
{
|
2008-02-18 12:31:23 +00:00
|
|
|
|
NSLog(@"gdnc - failed to register as %@", name);
|
2002-03-09 18:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a = [host addresses];
|
|
|
|
|
c = [a count];
|
|
|
|
|
while (c-- > 0)
|
|
|
|
|
{
|
|
|
|
|
NSString *name = [a objectAtIndex: c];
|
|
|
|
|
|
2002-12-12 15:14:13 +00:00
|
|
|
|
name = [service stringByAppendingFormat: @"-%@", name];
|
2002-03-09 18:21:20 +00:00
|
|
|
|
if ([ns registerPort: port forName: name] == NO)
|
|
|
|
|
{
|
2008-02-18 12:31:23 +00:00
|
|
|
|
NSLog(@"gdnc - failed to register as %@", name);
|
2002-03-09 18:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get notifications for new connections and connection losses.
|
|
|
|
|
*/
|
|
|
|
|
[conn setDelegate: self];
|
1999-06-17 10:53:24 +00:00
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
addObserver: self
|
|
|
|
|
selector: @selector(connectionBecameInvalid:)
|
|
|
|
|
name: NSConnectionDidDieNotification
|
|
|
|
|
object: conn];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) addObserver: (uint64_t)anObserver
|
1998-11-09 11:05:37 +00:00
|
|
|
|
selector: (NSString*)aSelector
|
1998-11-02 16:59:57 +00:00
|
|
|
|
name: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)anObject
|
|
|
|
|
suspensionBehavior: (NSNotificationSuspensionBehavior)suspensionBehavior
|
|
|
|
|
for: (id<GDNCClient>)client
|
|
|
|
|
{
|
|
|
|
|
GDNCClient *info;
|
|
|
|
|
NSMapTable *clients;
|
|
|
|
|
GDNCObserver *obs;
|
|
|
|
|
NSConnection *connection;
|
|
|
|
|
|
2008-11-27 15:01:19 +00:00
|
|
|
|
if (debugging)
|
2010-02-14 10:48:10 +00:00
|
|
|
|
NSLog(@"Adding observer %llu for %@ %@",
|
2011-08-16 16:04:43 +00:00
|
|
|
|
(unsigned long long)anObserver, notificationName, anObject);
|
2008-11-27 15:01:19 +00:00
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
connection = [(NSDistantObject*)client connectionForProxy];
|
|
|
|
|
clients = (NSMapTable*)NSMapGet(connections, connection);
|
|
|
|
|
if (clients == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"Unknown connection for new observer"];
|
|
|
|
|
}
|
|
|
|
|
info = (GDNCClient*)NSMapGet(clients, client);
|
|
|
|
|
if (info == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"Unknown client for new observer"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Create new observer info and add to array of observers for this
|
|
|
|
|
* client and the table of all observers.
|
|
|
|
|
*/
|
|
|
|
|
obs = [GDNCObserver new];
|
|
|
|
|
obs->observer = anObserver;
|
|
|
|
|
obs->client = info;
|
|
|
|
|
obs->behavior = suspensionBehavior;
|
1998-11-09 11:05:37 +00:00
|
|
|
|
obs->selector = [aSelector copy];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[info->observers addObject: obs];
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(obs);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
NSHashInsert(allObservers, obs);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now add the observer to the lists of observers interested in it's
|
|
|
|
|
* particular notification names and objects.
|
|
|
|
|
*/
|
|
|
|
|
if (anObject)
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *objList;
|
|
|
|
|
|
|
|
|
|
objList = [observersForObjects objectForKey: anObject];
|
|
|
|
|
if (objList == nil)
|
|
|
|
|
{
|
|
|
|
|
objList = [NSMutableArray new];
|
|
|
|
|
[observersForObjects setObject: objList forKey: anObject];
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(objList);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* If possible use an existing string as the key.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
*/
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if ([objList count] > 0)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *tmp = [objList objectAtIndex: 0];
|
|
|
|
|
|
|
|
|
|
anObject = tmp->notificationObject;
|
|
|
|
|
}
|
2000-07-03 13:18:07 +00:00
|
|
|
|
obs->notificationObject = RETAIN(anObject);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[objList addObject: obs];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (notificationName)
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *namList;
|
|
|
|
|
|
|
|
|
|
namList = [observersForNames objectForKey: notificationName];
|
|
|
|
|
if (namList == nil)
|
|
|
|
|
{
|
|
|
|
|
namList = [NSMutableArray new];
|
|
|
|
|
[observersForNames setObject: namList forKey: notificationName];
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(namList);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* If possible use an existing string as the key.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
*/
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if ([namList count] > 0)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *tmp = [namList objectAtIndex: 0];
|
|
|
|
|
|
2004-09-03 17:10:31 +00:00
|
|
|
|
notificationName = tmp->notificationName;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
2000-07-03 13:18:07 +00:00
|
|
|
|
obs->notificationName = RETAIN(notificationName);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[namList addObject: obs];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-03 13:18:07 +00:00
|
|
|
|
- (BOOL) connection: (NSConnection*)ancestor
|
2004-03-29 03:37:46 +00:00
|
|
|
|
shouldMakeNewConnection: (NSConnection*)newConn
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
NSMapTable *table;
|
|
|
|
|
|
1999-06-17 10:53:24 +00:00
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
addObserver: self
|
|
|
|
|
selector: @selector(connectionBecameInvalid:)
|
|
|
|
|
name: NSConnectionDidDieNotification
|
|
|
|
|
object: newConn];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[newConn setDelegate: self];
|
|
|
|
|
/*
|
|
|
|
|
* Create a new map table entry for this connection with a value that
|
|
|
|
|
* is a table (normally with a single entry) containing registered
|
|
|
|
|
* clients (proxies for NSDistributedNotificationCenter objects).
|
|
|
|
|
*/
|
|
|
|
|
table = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
|
|
|
|
NSObjectMapValueCallBacks, 0);
|
|
|
|
|
NSMapInsert(connections, newConn, table);
|
2016-06-24 10:44:40 +00:00
|
|
|
|
if (nil != timer)
|
|
|
|
|
{
|
|
|
|
|
[timer invalidate];
|
|
|
|
|
timer = nil;
|
|
|
|
|
}
|
2000-07-03 13:18:07 +00:00
|
|
|
|
return YES;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (id) connectionBecameInvalid: (NSNotification*)notification
|
|
|
|
|
{
|
|
|
|
|
id connection = [notification object];
|
|
|
|
|
|
1999-06-17 10:53:24 +00:00
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
|
removeObserver: self
|
|
|
|
|
name: NSConnectionDidDieNotification
|
|
|
|
|
object: connection];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
if (connection == conn)
|
|
|
|
|
{
|
2002-03-09 18:21:20 +00:00
|
|
|
|
NSLog(@"argh - gdnc server root connection has been destroyed.");
|
2003-05-12 20:42:47 +00:00
|
|
|
|
exit(EXIT_FAILURE);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSMapTable *table;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove all clients registered via this connection
|
|
|
|
|
* (should normally only be 1) - then the connection.
|
|
|
|
|
*/
|
|
|
|
|
table = NSMapGet(connections, connection);
|
1999-10-12 18:05:27 +00:00
|
|
|
|
NSMapRemove(connections, connection);
|
|
|
|
|
if (table != 0)
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
[self removeObserversForClients: table];
|
|
|
|
|
NSFreeMapTable(table);
|
|
|
|
|
}
|
2007-03-06 18:38:22 +00:00
|
|
|
|
|
|
|
|
|
if (auto_stop == YES && NSCountMapTable(connections) == 0)
|
|
|
|
|
{
|
2016-06-24 10:44:40 +00:00
|
|
|
|
/* There is nothing left using this notification center,
|
|
|
|
|
* so schedule the auto_stop to occur in a short while
|
|
|
|
|
* if nothing has connected to us.
|
|
|
|
|
*/
|
|
|
|
|
if (nil != timer)
|
|
|
|
|
{
|
|
|
|
|
[timer invalidate];
|
|
|
|
|
}
|
|
|
|
|
timer = [NSTimer scheduledTimerWithTimeInterval: 15.0
|
|
|
|
|
target: self
|
|
|
|
|
selector: @selector(autoStop:)
|
|
|
|
|
userInfo: nil
|
|
|
|
|
repeats: NO];
|
2007-03-06 18:38:22 +00:00
|
|
|
|
}
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
1999-06-24 19:30:29 +00:00
|
|
|
|
return nil;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) registerClient: (id<GDNCClient>)client
|
|
|
|
|
{
|
|
|
|
|
NSMapTable *table;
|
|
|
|
|
GDNCClient *info;
|
|
|
|
|
|
|
|
|
|
table = NSMapGet(connections, [(NSDistantObject*)client connectionForProxy]);
|
|
|
|
|
if (table == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"registration with unknown connection"];
|
|
|
|
|
}
|
|
|
|
|
if (NSMapGet(table, client) != 0)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
{
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"registration with registered client"];
|
|
|
|
|
}
|
|
|
|
|
info = [GDNCClient new];
|
2003-07-04 16:27:02 +00:00
|
|
|
|
if ([(id)client isProxy] == YES)
|
|
|
|
|
{
|
|
|
|
|
Protocol *p = @protocol(GDNCClient);
|
|
|
|
|
|
|
|
|
|
[(id)client setProtocolForProxy: p];
|
|
|
|
|
}
|
1998-11-02 16:59:57 +00:00
|
|
|
|
info->client = client;
|
|
|
|
|
NSMapInsert(table, client, info);
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(info);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-27 13:05:26 +00:00
|
|
|
|
- (oneway void) postNotificationName: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)notificationObject
|
|
|
|
|
userInfo: (NSData*)d
|
|
|
|
|
deliverImmediately: (BOOL)deliverImmediately
|
|
|
|
|
for: (id<GDNCClient>)client
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
NSMutableArray *observers = [NSMutableArray array];
|
|
|
|
|
NSMutableArray *byName;
|
|
|
|
|
NSMutableArray *byObject;
|
|
|
|
|
unsigned pos;
|
2018-01-31 14:40:11 +00:00
|
|
|
|
GDNCNotification *notification;
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
byName = [observersForNames objectForKey: notificationName];
|
|
|
|
|
byObject = [observersForObjects objectForKey: notificationObject];
|
|
|
|
|
/*
|
|
|
|
|
* Build up a list of all those observers that should get sent this.
|
|
|
|
|
*/
|
|
|
|
|
for (pos = [byName count]; pos > 0; pos--)
|
|
|
|
|
{
|
1998-11-09 11:05:37 +00:00
|
|
|
|
GDNCObserver *obs = [byName objectAtIndex: pos - 1];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
2002-03-20 12:59:45 +00:00
|
|
|
|
if (obs->notificationObject == nil
|
|
|
|
|
|| [obs->notificationObject isEqual: notificationObject])
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
[observers addObject: obs];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (pos = [byObject count]; pos > 0; pos--)
|
|
|
|
|
{
|
1998-11-09 11:05:37 +00:00
|
|
|
|
GDNCObserver *obs = [byObject objectAtIndex: pos - 1];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
2002-03-20 12:59:45 +00:00
|
|
|
|
if (obs->notificationName == nil
|
|
|
|
|
|| [obs->notificationName isEqual: notificationName])
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
if ([observers indexOfObjectIdenticalTo: obs] == NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
[observers addObject: obs];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 14:40:11 +00:00
|
|
|
|
if ([observers count] == 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
/*
|
|
|
|
|
* Build notification object to queue for observer.
|
|
|
|
|
*/
|
2018-01-31 14:40:11 +00:00
|
|
|
|
notification = [GDNCNotification notificationWithName: notificationName
|
|
|
|
|
object: notificationObject
|
|
|
|
|
data: d];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Add the object to the queue for this observer depending on suspension
|
|
|
|
|
* state of the client NSDistributedNotificationCenter etc.
|
|
|
|
|
*/
|
|
|
|
|
for (pos = [observers count]; pos > 0; pos--)
|
|
|
|
|
{
|
1998-11-09 11:05:37 +00:00
|
|
|
|
GDNCObserver *obs = [observers objectAtIndex: pos - 1];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
if (obs->client->suspended == NO || deliverImmediately == YES)
|
|
|
|
|
{
|
1998-11-09 11:05:37 +00:00
|
|
|
|
[obs->queue addObject: notification];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (obs->behavior)
|
|
|
|
|
{
|
|
|
|
|
case NSNotificationSuspensionBehaviorDrop:
|
|
|
|
|
break;
|
|
|
|
|
case NSNotificationSuspensionBehaviorCoalesce:
|
|
|
|
|
[obs->queue removeAllObjects];
|
1998-11-09 11:05:37 +00:00
|
|
|
|
[obs->queue addObject: notification];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
break;
|
|
|
|
|
case NSNotificationSuspensionBehaviorHold:
|
1998-11-09 11:05:37 +00:00
|
|
|
|
[obs->queue addObject: notification];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
break;
|
|
|
|
|
case NSNotificationSuspensionBehaviorDeliverImmediately:
|
1998-11-09 11:05:37 +00:00
|
|
|
|
[obs->queue addObject: notification];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Now perform the actual posting of the notification to the observers in
|
|
|
|
|
* our array.
|
|
|
|
|
*/
|
|
|
|
|
for (pos = [observers count]; pos > 0; pos--)
|
|
|
|
|
{
|
1998-11-09 11:05:37 +00:00
|
|
|
|
GDNCObserver *obs = [observers objectAtIndex: pos - 1];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
|
|
|
|
|
if (obs->client->suspended == NO || deliverImmediately == YES)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Post notifications to the observer until:
|
|
|
|
|
* an exception (obs is set to nil)
|
|
|
|
|
* the queue is empty ([obs->queue count] == 0)
|
|
|
|
|
* the observer is removed (obs is not in allObservers)
|
|
|
|
|
*/
|
2002-12-12 15:14:13 +00:00
|
|
|
|
while (obs != nil && [obs->queue count] > 0
|
|
|
|
|
&& NSHashGet(allObservers, obs) != 0)
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
2004-09-03 17:10:31 +00:00
|
|
|
|
GDNCNotification *n;
|
|
|
|
|
n = RETAIN([obs->queue objectAtIndex: 0]);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
|
|
|
|
[obs->queue removeObjectAtIndex: 0];
|
2008-11-27 15:01:19 +00:00
|
|
|
|
if (debugging)
|
2011-08-16 16:04:43 +00:00
|
|
|
|
NSLog(@"Posting to observer %llu with %@", (unsigned long long)obs->observer, n);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[obs->client->client postNotificationName: n->name
|
|
|
|
|
object: n->object
|
|
|
|
|
userInfo: n->info
|
|
|
|
|
selector: obs->selector
|
|
|
|
|
to: obs->observer];
|
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
2004-09-03 17:10:31 +00:00
|
|
|
|
obs = nil;
|
2008-11-27 15:49:52 +00:00
|
|
|
|
NSLog(@"Problem posting notification to client: %@",
|
|
|
|
|
localException);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
2004-09-03 17:10:31 +00:00
|
|
|
|
RELEASE(n);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-29 03:37:46 +00:00
|
|
|
|
- (void) removeObserver: (GDNCObserver*)observer
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
2008-11-27 15:01:19 +00:00
|
|
|
|
if (debugging)
|
2010-02-14 10:48:10 +00:00
|
|
|
|
NSLog(@"Removing observer %llu for %@ %@",
|
2011-08-16 16:04:43 +00:00
|
|
|
|
(unsigned long long)observer->observer, observer->notificationName,
|
2008-11-27 15:01:19 +00:00
|
|
|
|
observer->notificationObject);
|
|
|
|
|
|
2004-03-29 03:37:46 +00:00
|
|
|
|
if (observer->notificationObject)
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
NSMutableArray *objList;
|
|
|
|
|
|
2004-03-29 03:37:46 +00:00
|
|
|
|
objList= [observersForObjects objectForKey: observer->notificationObject];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if (objList != nil)
|
|
|
|
|
{
|
2004-03-29 03:37:46 +00:00
|
|
|
|
[objList removeObjectIdenticalTo: observer];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-03-29 03:37:46 +00:00
|
|
|
|
if (observer->notificationName)
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
NSMutableArray *namList;
|
|
|
|
|
|
2004-03-29 03:37:46 +00:00
|
|
|
|
namList = [observersForNames objectForKey: observer->notificationName];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if (namList != nil)
|
|
|
|
|
{
|
2004-03-29 03:37:46 +00:00
|
|
|
|
[namList removeObjectIdenticalTo: observer];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-03-29 03:37:46 +00:00
|
|
|
|
NSHashRemove(allObservers, observer);
|
|
|
|
|
[observer->client->observers removeObjectIdenticalTo: observer];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) removeObserversForClients: (NSMapTable*)clients
|
|
|
|
|
{
|
|
|
|
|
NSMapEnumerator enumerator;
|
|
|
|
|
NSObject *client;
|
|
|
|
|
GDNCClient *info;
|
|
|
|
|
|
|
|
|
|
enumerator = NSEnumerateMapTable(clients);
|
|
|
|
|
while (NSNextMapEnumeratorPair(&enumerator,
|
|
|
|
|
(void**)&client, (void**)&info) == YES)
|
|
|
|
|
{
|
|
|
|
|
while ([info->observers count] > 0)
|
|
|
|
|
{
|
|
|
|
|
[self removeObserver: [info->observers objectAtIndex: 0]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
|
- (void) removeObserver: (uint64_t)anObserver
|
1998-11-02 16:59:57 +00:00
|
|
|
|
name: (NSString*)notificationName
|
|
|
|
|
object: (NSString*)notificationObject
|
|
|
|
|
for: (id<GDNCClient>)client
|
|
|
|
|
{
|
|
|
|
|
if (anObserver == 0)
|
|
|
|
|
{
|
|
|
|
|
if (notificationName == nil)
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *observers;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* No notification name - so remove all with matching object.
|
|
|
|
|
*/
|
|
|
|
|
observers = [observersForObjects objectForKey: notificationObject];
|
|
|
|
|
while ([observers count] > 0)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *obs;
|
|
|
|
|
|
|
|
|
|
obs = [observers objectAtIndex: 0];
|
|
|
|
|
[self removeObserver: obs];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (notificationObject == nil)
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *observers;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* No notification object - so remove all with matching name.
|
|
|
|
|
*/
|
|
|
|
|
observers = [observersForObjects objectForKey: notificationName];
|
|
|
|
|
while ([observers count] > 0)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *obs;
|
|
|
|
|
|
|
|
|
|
obs = [observers objectAtIndex: 0];
|
|
|
|
|
[self removeObserver: obs];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSMutableArray *byName;
|
|
|
|
|
NSMutableArray *byObject;
|
|
|
|
|
unsigned pos;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Remove observers that match both name and object.
|
|
|
|
|
*/
|
|
|
|
|
byName = [observersForObjects objectForKey: notificationName];
|
|
|
|
|
byObject = [observersForObjects objectForKey: notificationName];
|
|
|
|
|
for (pos = [byName count]; pos > 0; pos--)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *obs;
|
|
|
|
|
|
1998-11-09 11:05:37 +00:00
|
|
|
|
obs = [byName objectAtIndex: pos - 1];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if ([byObject indexOfObjectIdenticalTo: obs] != NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
[self removeObserver: obs];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
}
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
for (pos = [byObject count]; pos > 0; pos--)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *obs;
|
|
|
|
|
|
1998-11-09 11:05:37 +00:00
|
|
|
|
obs = [byObject objectAtIndex: pos - 1];
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if ([byName indexOfObjectIdenticalTo: obs] != NSNotFound)
|
|
|
|
|
{
|
|
|
|
|
[self removeObserver: obs];
|
2005-02-22 11:22:44 +00:00
|
|
|
|
}
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSMapTable *table;
|
|
|
|
|
GDNCClient *info;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If an observer object (as an unsigned) was specified then
|
|
|
|
|
* the observer MUST be from this client - so we can look
|
|
|
|
|
* through the per-client list of objects.
|
|
|
|
|
*/
|
|
|
|
|
table = NSMapGet(connections,
|
|
|
|
|
[(NSDistantObject*)client connectionForProxy]);
|
|
|
|
|
if (table == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"removeObserver with unknown connection"];
|
|
|
|
|
}
|
|
|
|
|
info = (GDNCClient*)NSMapGet(table, client);
|
|
|
|
|
if (info != nil)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
{
|
1998-11-02 16:59:57 +00:00
|
|
|
|
unsigned pos = [info->observers count];
|
|
|
|
|
|
|
|
|
|
while (pos > 0)
|
|
|
|
|
{
|
|
|
|
|
GDNCObserver *obs = [info->observers objectAtIndex: --pos];
|
|
|
|
|
|
|
|
|
|
if (obs->observer == anObserver)
|
|
|
|
|
{
|
|
|
|
|
if (notificationName == nil ||
|
|
|
|
|
[notificationName isEqual: obs->notificationName])
|
|
|
|
|
{
|
|
|
|
|
if (notificationObject == nil ||
|
|
|
|
|
[notificationObject isEqual: obs->notificationObject])
|
|
|
|
|
{
|
|
|
|
|
[self removeObserver: obs];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) setSuspended: (BOOL)flag
|
|
|
|
|
for: (id<GDNCClient>)client
|
|
|
|
|
{
|
|
|
|
|
NSMapTable *table;
|
|
|
|
|
GDNCClient *info;
|
|
|
|
|
|
|
|
|
|
table = NSMapGet(connections, [(NSDistantObject*)client connectionForProxy]);
|
|
|
|
|
if (table == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"setSuspended: with unknown connection"];
|
|
|
|
|
}
|
|
|
|
|
info = (GDNCClient*)NSMapGet(table, client);
|
|
|
|
|
if (info == nil)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"setSuspended: with unregistered client"];
|
|
|
|
|
}
|
|
|
|
|
info->suspended = flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void) unregisterClient: (id<GDNCClient>)client
|
|
|
|
|
{
|
|
|
|
|
NSMapTable *table;
|
|
|
|
|
GDNCClient *info;
|
|
|
|
|
|
|
|
|
|
table = NSMapGet(connections, [(NSDistantObject*)client connectionForProxy]);
|
|
|
|
|
if (table == 0)
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"unregistration with unknown connection"];
|
|
|
|
|
}
|
|
|
|
|
info = (GDNCClient*)NSMapGet(table, client);
|
|
|
|
|
if (info == nil)
|
2005-02-22 11:22:44 +00:00
|
|
|
|
{
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[NSException raise: NSInternalInconsistencyException
|
|
|
|
|
format: @"unregistration with unregistered client"];
|
|
|
|
|
}
|
|
|
|
|
while ([info->observers count] > 0)
|
|
|
|
|
{
|
|
|
|
|
[self removeObserver: [info->observers objectAtIndex: 0]];
|
|
|
|
|
}
|
|
|
|
|
NSMapRemove(table, client);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
2004-03-29 03:37:46 +00:00
|
|
|
|
|
2005-07-23 18:39:38 +00:00
|
|
|
|
/**
|
|
|
|
|
<p>The gdnc daemon is used by GNUstep programs to send notifications and
|
|
|
|
|
messages to one another, in conjunction with the Base library
|
|
|
|
|
Notification-related classes.</p>
|
|
|
|
|
|
|
|
|
|
<p>Every user needs to have his own instance of gdnc running. While gdnc
|
|
|
|
|
will be started automatically as soon as it is needed, it is recommended
|
|
|
|
|
to start gdnc in a personal login script like ~/.bashrc or ~/.cshrc.
|
|
|
|
|
Alternatively (if you have no command-line tools which use distributed
|
|
|
|
|
notifications) you can launch gdnc when your windowing system or the
|
|
|
|
|
window manager is started. For example, on systems with X11 you can
|
|
|
|
|
launch gdnc from your .xinitrc script or alternatively - if you are
|
|
|
|
|
running Window Maker - put it in Window Maker's autostart script. See
|
|
|
|
|
the GNUstep Build Guide for a sample startup script.</p>
|
|
|
|
|
|
|
|
|
|
<p>Please see the man page for more information.</p>
|
|
|
|
|
*/
|
1998-11-02 16:59:57 +00:00
|
|
|
|
int
|
2000-06-29 03:51:06 +00:00
|
|
|
|
main(int argc, char** argv, char** env)
|
1998-11-02 16:59:57 +00:00
|
|
|
|
{
|
|
|
|
|
GDNCServer *server;
|
2005-02-08 10:11:18 +00:00
|
|
|
|
BOOL subtask = YES;
|
|
|
|
|
NSProcessInfo *pInfo;
|
2005-02-08 11:57:39 +00:00
|
|
|
|
NSMutableArray *args;
|
2000-07-03 13:18:07 +00:00
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
1998-11-09 11:05:37 +00:00
|
|
|
|
|
2000-06-29 03:51:06 +00:00
|
|
|
|
#ifdef GS_PASS_ARGUMENTS
|
2009-10-12 14:38:49 +00:00
|
|
|
|
GSInitializeProcess(argc, argv, env);
|
2000-06-29 03:51:06 +00:00
|
|
|
|
#endif
|
2014-07-01 21:16:22 +00:00
|
|
|
|
//[NSObject enableDoubleReleaseCheck: YES];
|
2005-02-08 10:11:18 +00:00
|
|
|
|
pInfo = [NSProcessInfo processInfo];
|
2005-02-08 11:57:39 +00:00
|
|
|
|
args = AUTORELEASE([[pInfo arguments] mutableCopy]);
|
|
|
|
|
|
|
|
|
|
if ([[pInfo arguments] containsObject: @"--help"] == YES)
|
|
|
|
|
{
|
|
|
|
|
printf("gdnc\n\n");
|
|
|
|
|
printf("GNU Distributed Notification Center\n");
|
|
|
|
|
printf("--help\tfor help\n");
|
|
|
|
|
printf("--no-fork\tavoid fork() to make debugging easy\n");
|
|
|
|
|
printf("--verbose\tMore verbose debug output\n");
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
}
|
2007-03-06 18:38:22 +00:00
|
|
|
|
if ([[pInfo arguments] containsObject: @"--auto"] == YES)
|
|
|
|
|
{
|
|
|
|
|
auto_stop = YES;
|
|
|
|
|
}
|
2005-02-08 11:57:39 +00:00
|
|
|
|
if ([[pInfo arguments] containsObject: @"--daemon"] == YES)
|
|
|
|
|
{
|
|
|
|
|
subtask = NO;
|
|
|
|
|
is_daemon = YES;
|
|
|
|
|
}
|
|
|
|
|
if ([[pInfo arguments] containsObject: @"-f"] == YES
|
|
|
|
|
|| [[pInfo arguments] containsObject: @"--no-fork"] == YES)
|
2002-03-20 12:59:45 +00:00
|
|
|
|
{
|
2005-02-08 10:11:18 +00:00
|
|
|
|
subtask = NO;
|
2002-03-20 12:59:45 +00:00
|
|
|
|
}
|
2005-02-08 11:57:39 +00:00
|
|
|
|
if ([[pInfo arguments] containsObject: @"--verbose"] == YES)
|
|
|
|
|
{
|
|
|
|
|
debugging = YES;
|
|
|
|
|
}
|
2005-02-08 10:11:18 +00:00
|
|
|
|
if ([[NSUserDefaults standardUserDefaults] boolForKey: @"debug"] == YES)
|
1998-11-09 11:05:37 +00:00
|
|
|
|
{
|
2005-02-08 10:11:18 +00:00
|
|
|
|
subtask = NO;
|
2002-05-10 06:59:50 +00:00
|
|
|
|
debugging = YES;
|
1998-11-09 11:05:37 +00:00
|
|
|
|
}
|
2004-11-20 20:14:24 +00:00
|
|
|
|
|
2005-02-08 10:11:18 +00:00
|
|
|
|
if (subtask)
|
2002-03-20 12:59:45 +00:00
|
|
|
|
{
|
2005-02-08 10:11:18 +00:00
|
|
|
|
NSFileHandle *null;
|
|
|
|
|
NSTask *t;
|
1998-11-06 14:43:07 +00:00
|
|
|
|
|
2005-02-08 10:11:18 +00:00
|
|
|
|
t = [NSTask new];
|
|
|
|
|
NS_DURING
|
2003-09-01 00:46:26 +00:00
|
|
|
|
{
|
2005-02-10 00:04:32 +00:00
|
|
|
|
[args removeObjectAtIndex: 0];
|
2005-02-08 11:57:39 +00:00
|
|
|
|
[args addObject: @"--daemon"];
|
2005-02-08 10:11:18 +00:00
|
|
|
|
[t setLaunchPath: [[NSBundle mainBundle] executablePath]];
|
|
|
|
|
[t setArguments: args];
|
|
|
|
|
[t setEnvironment: [pInfo environment]];
|
|
|
|
|
null = [NSFileHandle fileHandleWithNullDevice];
|
|
|
|
|
[t setStandardInput: null];
|
|
|
|
|
[t setStandardOutput: null];
|
|
|
|
|
[t setStandardError: null];
|
|
|
|
|
[t launch];
|
|
|
|
|
DESTROY(t);
|
2004-11-20 20:14:24 +00:00
|
|
|
|
}
|
2005-02-08 10:11:18 +00:00
|
|
|
|
NS_HANDLER
|
2004-11-20 20:14:24 +00:00
|
|
|
|
{
|
2009-01-25 08:41:30 +00:00
|
|
|
|
gdnc_log(LOG_CRIT, [[localException description] UTF8String]);
|
2005-02-08 10:11:18 +00:00
|
|
|
|
DESTROY(t);
|
2004-11-20 20:14:24 +00:00
|
|
|
|
}
|
2005-02-08 10:11:18 +00:00
|
|
|
|
NS_ENDHANDLER
|
2003-09-01 00:46:26 +00:00
|
|
|
|
exit(EXIT_FAILURE);
|
2004-11-20 20:14:24 +00:00
|
|
|
|
}
|
2005-02-08 10:11:18 +00:00
|
|
|
|
RELEASE(pool);
|
2003-09-01 00:46:26 +00:00
|
|
|
|
|
2000-07-03 13:18:07 +00:00
|
|
|
|
{
|
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
2003-05-13 05:24:32 +00:00
|
|
|
|
NSUserDefaults *defs;
|
|
|
|
|
int sym;
|
|
|
|
|
|
|
|
|
|
for (sym = 0; sym < NSIG; sym++)
|
|
|
|
|
{
|
2007-05-30 11:06:19 +00:00
|
|
|
|
if (sym == SIGABRT) continue;
|
2006-06-29 09:26:57 +00:00
|
|
|
|
#ifdef SIGPROF
|
|
|
|
|
if (sym == SIGPROF) continue;
|
|
|
|
|
#endif
|
2003-05-13 05:24:32 +00:00
|
|
|
|
signal(sym, ihandler);
|
|
|
|
|
}
|
2021-01-18 13:20:14 +00:00
|
|
|
|
#ifndef _WIN32
|
2003-05-13 05:24:32 +00:00
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
signal(SIGTTOU, SIG_IGN);
|
|
|
|
|
signal(SIGTTIN, SIG_IGN);
|
|
|
|
|
signal(SIGHUP, SIG_IGN);
|
|
|
|
|
#endif
|
|
|
|
|
signal(SIGTERM, ihandler);
|
2002-05-10 06:59:50 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Make gdnc logging go to syslog unless overridden by user.
|
|
|
|
|
*/
|
2003-05-13 05:24:32 +00:00
|
|
|
|
defs = [NSUserDefaults standardUserDefaults];
|
2002-05-10 06:59:50 +00:00
|
|
|
|
[defs registerDefaults: [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
@"YES", @"GSLogSyslog", nil]];
|
|
|
|
|
|
2000-07-03 13:18:07 +00:00
|
|
|
|
server = [GDNCServer new];
|
2002-05-10 06:59:50 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Close standard input, output, and error to run as daemon.
|
|
|
|
|
*/
|
|
|
|
|
[[NSFileHandle fileHandleWithStandardInput] closeFile];
|
|
|
|
|
[[NSFileHandle fileHandleWithStandardOutput] closeFile];
|
2010-03-19 12:10:11 +00:00
|
|
|
|
#ifndef __MINGW__
|
2002-05-10 06:59:50 +00:00
|
|
|
|
if (debugging == NO)
|
|
|
|
|
{
|
|
|
|
|
[[NSFileHandle fileHandleWithStandardError] closeFile];
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-07-03 13:18:07 +00:00
|
|
|
|
RELEASE(pool);
|
|
|
|
|
}
|
|
|
|
|
|
1998-11-02 16:59:57 +00:00
|
|
|
|
if (server != nil)
|
|
|
|
|
{
|
2002-03-25 08:13:46 +00:00
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
[[NSRunLoop currentRunLoop] run];
|
2002-03-25 08:13:46 +00:00
|
|
|
|
RELEASE(pool);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
2003-05-12 20:42:47 +00:00
|
|
|
|
exit(EXIT_SUCCESS);
|
1998-11-02 16:59:57 +00:00
|
|
|
|
}
|
|
|
|
|
|