This is NetTalkClient.m in view mode; [Download] [Up]
#import "NetTalkClient.h"
#import "TalkController.h"
#import "NetTalkThinker.h"
#import <appkit/appkit.h>
#include <sys/types.h>
#include <ansi/ctype.h>
#include <bsd/pwd.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <sys/param.h>
#include <netdb.h>
@implementation NetTalkClient
- init
{
int retry;
id serverConnection;
char *serverName, serverList[8192];
[super init];
delegate = nil;
sprintf(hostname, "%s", [self fullHostname]);
realName = (char *)[self user];
strncpy(talkName, NXUserName(), 127);
uniqueName[0] = 0;
serverStarter = NO;
strcpy(serverList, NXGetDefaultValue(APPNAME, NTD_SERVERLIST));
if (serverList[0] == 0)
{
retry = 1;
while (retry)
{
server = [NXConnection connectToName:NETTALK onHost:"*"];
if (!server)
{
retry = [self thereIsNoServer];
if (!retry)
{
[self free];
return nil;
}
}
else
{
fprintf(stderr, "NetTalk: Connected to local server.\n");
retry = 0;
}
}
}
else
{
strcpy(serverList, NXGetDefaultValue(APPNAME, NTD_SERVERLIST));
serverName = strtok(serverList, " ");
while (serverName)
{
server = [NXConnection connectToName:NETTALK onHost:serverName];
if (!server)
serverName = strtok(NULL, " ");
else
{
fprintf(stderr, "NetTalk: Connected to server %s.\n", serverName);
strcpy(currentServerName, serverName);
serverName = NULL;
}
}
if (!server)
{
if (NXRunLocalizedAlertPanel(NULL
, "Alert", "NoDemonOnServer-1-Name", "OK", "Terminate", NULL
, serverName)
== NX_ALERTALTERNATE)
{
[self free];
return nil;
}
}
}
serverConnection = [server connectionForProxy];
[server setProtocolForProxy:@protocol(NTKPserver)];
[serverConnection registerForInvalidationNotification:self];
[serverConnection runFromAppKit];
[server addClient:self];
return self;
}
- setDelegate:aDelegate
{
delegate = aDelegate;
return self;
}
- delegate
{
return delegate;
}
/*****************************************************************/
/* - (id) startupServer (->self) */
/* Fork subprocess and make it the server. */
/*****************************************************************/
- (id) startupServer
{
char servername[MAXPATHLEN+1];
int childPid;
[[NXBundle mainBundle]
getPath:servername forResource:"nettalkd" ofType:NULL];
switch (childPid = vfork())
{
/* error */
case -1:
perror("vfork (child)");
break;
/* child */
case 0:
execl(servername, 0);
perror("vfork (child)"); /* should never gets here tho */
exit(1);
/* me */
default:
fprintf(stderr, "Started server <%d>.\n", childPid);
sleep(2);
}
return self;
}
/*****************************************************************/
/* - (int) thereIsNoServer */
/* Informs the user that there is no server. */
/* Asks weather to retry searching (1) */
/* or to terminate the application. (0) */
/*****************************************************************/
- (int) thereIsNoServer
{
switch(NXRunLocalizedAlertPanel(NULL
, "Alert"
, "NoServer"
, "Retry", "Start server", "Terminate"))
{
case NX_ALERTDEFAULT:
return 1;
break;
case NX_ALERTALTERNATE:
[self startupServer];
return 1;
break;
case NX_ALERTOTHER:
return 0;
}
return 0;
}
- (id) server
{
return server;
}
- (const char *)serverName
{
return currentServerName;
}
/*****************************************************************/
/* - (const char *) user */
/* Returns the real user name, taken from NetInfo. */
/* */
/* Thanks to */
/* droege@informatik.uni-koblenz.de for the code. */
/*******************************************************/
- (const char *)user
{
static char *username = (char *)0;
struct passwd *pwdentry;
static char ubuf[128];
char *pc;
pwdentry = getpwnam(NXUserName());
username = ((pwdentry) ? pwdentry->pw_gecos : "");
/*
* extended GECOS field handling, Detlev Droege,
* droege@informatik.uni-koblenz.de, December 1991
*/
if (pc = index(username, ','))
*pc = 0; /* strip ','-part of gecos field, clobbers
* pw_gecos !! */
if (index(username, '&'))
{
/* do '&' expansion */
pc = ubuf;
while (*username)
{
if (*username == '&')
{
strcpy(pc, pwdentry->pw_name);
*pc = toupper(*pc);
while (*pc)
pc++; /* == pc += strlen(..->pw_name) */
}
else
*pc++ = *username;
username++;
}
*pc = 0;
username = ubuf;
}
return (const char *)username;
}
- (const char*)fullHostname
{
static char host[MAXHOSTNAMELEN];
int status, hlen, dlen;
/* Get the host name */
status = gethostname(host, MAXHOSTNAMELEN);
if (status < 0) return(NULL);
hlen = strlen(host);
/* res_init() will look up the domain name */
res_init();
/* If there's no domain name set, _res.defdname is zero length */
dlen = strlen(_res.defdname);
if (dlen == 0) return(host);
/* Append the domain name to the host name if necessary */
if ((hlen < dlen) || strcmp(host + (hlen - dlen), _res.defdname))
{
strcat(host, ".");
strcat(host, _res.defdname);
}
return(host);
}
- free
{
[super free];
[[server connectionForProxy] free];
return self;
}
- (const char *)registrationKey
{
return registrationKey;
}
- (int)registrationNr
{
return 0;
}
/*****************************************************************/
/* Methods the delegate and other interested folks should invoke */
/*****************************************************************/
- (id)
sendRefuseTo:(const char *)uName
forCode:(const char *)aCode
{
[server refuseConnection:self to:uName forCode:aCode];
return self;
}
- (id)
sendConnectTo:(const char *)uName
via:aDocument
withCode:(const char *)aCode
topicIs:(const char *)aTopic
{
[server connect:self to:uName via:aDocument withCode:aCode topicIs:aTopic];
return self;
}
/*****************************************************************/
/* Methods from the NetTalkClient protocol */
/*****************************************************************/
- (const char *)clientName
{
static char cName[MAXPATHLEN];
sprintf(cName, "%s @ %s", realName, hostname);
return cName;
}
- (const char *)userName
{
return talkName;
}
- (const char *)realUserName
{
return realName;
}
- (const char *)uniqueName
{
int pid;
if (uniqueName[0] == 0)
{
unix_pid(task_self(), &pid);
sprintf(uniqueName, "%s@%s|%i", talkName, hostname, pid);
}
return uniqueName;
}
- (BOOL) isServerStarter
{
return serverStarter;
}
- (oneway void) setServerStarter:(BOOL)aFlag
{
serverStarter = aFlag;
}
- sendDisconnectTo:(const char *)uName
{
[server
disconnect:self
from:uName
forCode:NULL];
return self;
}
- sendDisconnectTo:(const char *)uName
forCode:(const char *)aCode
{
[server disconnect:self from:uName forCode:aCode];
return self;
}
- getClientList
{
return [server clientList];
}
- (oneway void)newClientNamed:(const char *)uName
{
if ([delegate respondsTo:@selector(updateClientData)])
[delegate updateClientData];
free((char *)uName);
}
/*****************************************************************/
/* - client:sendsVia:forCode:topicIs: */
/*****************************************************************/
- (oneway void)
client:(in const char *)uName
sendsVia:aDocument
forCode:(const char *)aCode
topicIs:(in const char *)aTopic;
{
if (!aCode) aCode = "";
if (!aTopic) aTopic = "";
if ([delegate respondsTo:@selector(handleConnectFrom:via:withCode:topicIs:)])
[delegate
handleConnectFrom:uName
via:aDocument
withCode:aCode
topicIs:aTopic];
free((char *)aCode);
free((char *)aTopic);
}
- (oneway void)
client:(in const char *)uName
refusesConnectionForCode:(const char *)aCode
{
if (!aCode) aCode = "";
if ([delegate respondsTo:@selector(handleRefuseFrom:forCode:)])
[delegate
handleRefuseFrom:uName
forCode:(const char *)aCode];
free((char *)uName);
free((char *)aCode);
}
- (oneway void)
client:(in const char *)uName
wantsToDisconnectForCode:(const char *)aCode
{
if (!aCode) aCode = "";
if ([delegate respondsTo:@selector(handleDisconnectFrom:forCode:)])
[delegate
handleDisconnectFrom:uName
forCode:aCode];
free((char *)uName);
free((char *)aCode);
}
/*****************************************************************/
/* From the NXSenderIsInvalid protocol */
/* */
/* - senderIsInvalid:sender (->self) */
/*****************************************************************/
- senderIsInvalid:sender
{
id serverConnection;
int retry = 1;
int tries = 0;
char *serverName, serverList[8192];
if (strcmp(NXGetDefaultValue(APPNAME, NTD_USESELECTED), NTD_YES) == 0)
{
strcpy(serverList, NXGetDefaultValue(APPNAME, NTD_SERVERLIST));
serverName = strtok(serverList, " ");
while (serverName)
{
server = [NXConnection connectToName:NETTALK onHost:serverName];
if (!server)
serverName = strtok(NULL, " ");
else
{
fprintf(stderr, "NetTalk: Now connected to server %s.\n", serverName);
strcpy(currentServerName, serverName);
serverName = NULL;
}
}
if (!server)
{
switch(NXRunAlertPanel(NULL
, "Alert"
, "Lost connection to server!"
, "Continue", "Terminate", NULL))
{
case NX_ALERTDEFAULT:
break;
case NX_ALERTALTERNATE:
[NXApp terminate:nil];
break;
}
server = nil;
return 0;
}
}
else
{
if (serverStarter)
{
[self startupServer];
[self setServerStarter:NO];
}
while (retry)
{
server = [NXConnection connectToName:NETTALK onHost:"*"];
if (!server)
{
tries++;
if (tries > 2)
{
retry = [self thereIsNoServer];
tries = 0;
}
if (!retry)
[NXApp terminate:self];
}
else
{
fprintf(stderr, "NetTalk: Connected to local server.\n");
retry = 0;
}
}
}
serverConnection = [server connectionForProxy];
[server setProtocolForProxy:@protocol(NTKPserver)];
[serverConnection registerForInvalidationNotification:self];
[serverConnection runFromAppKit];
[server addClient:self];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.