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.