home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-06-29 | 41.6 KB | 1,406 lines |
- //*****************************************************************************
- //
- // Coordinator.m
- //
- // NXApp delegate, central control object for GateKeeper
- //
- // by Felipe A. Rodriguez
- //
- // The base for this file was:
- //
- // Coordinator.m
- // by Joe Freeman, David LaVallee
- // Subprocess Example, Release 2.0
- // NeXT Computer, Inc.
- //
- // This code is supplied "as is" the author makes no warranty as to its
- // suitability for any purpose. This code is free and may be distributed
- // in accordance with the terms of the:
- //
- // GNU GENERAL PUBLIC LICENSE
- // Version 2, June 1991
- // copyright (C) 1989, 1991 Free Software Foundation, Inc.
- // 675 Mass Ave, Cambridge, MA 02139, USA
- //
- //*****************************************************************************
-
- #import "GKdefs.h"
- #import "Animator.h"
- #import "Parse.h"
- #import "OptionsEditor.h"
- #import "options.h"
- #import "IconView.h"
- #import "ToolBar.h"
- #import "DOserver.h"
- #import "Timer.h"
- #import "InactivityTimer.h"
- #import "Coordinator.h"
- #import "CommandScroll.h"
- #import "Subprocess.h"
- #import "GateDocEditor.h"
- #import "HLRecord.h"
- #import "HLDelegate.h"
-
- #import <appkit/nextstd.h>
- #import <appkit/Application.h>
- #import <dpsclient/dpsNeXT.h>
- #import <objc/NXStringTable.h>
- #import <defaults/defaults.h>
- #import <bsd/c.h>
- #import <sys/dir.h> /* POSIX applications #include <dirent.h> */
-
-
-
-
- @interface Coordinator(Private)
-
- // preferences controls
- extern char *cList[];
- extern char *rfList[];
- extern char *rsList[];
-
- // private functions
- - miscPrep2;
-
- // dial on demand server
- #import <mach/mach_error.h>
- #import <servers/netname.h>
- #import "nsRPC_types.h"
-
-
- any_t server_loop(any_t port);
-
- // defined by MiG:
- boolean_t nsRPC_server(msg_header_t *in, msg_header_t *out);
-
- // from Request types in nsRPCUser.c
- struct message
- {
- msg_header_t head; /* standard header field */
- msg_type_t arg1_type; /* first arg type */
- int arg1; /* first arg */
- msg_type_t arg2_type; /* second arg type */
- int arg2; /* second arg */
- };
-
- @end
- @implementation Coordinator(Private)
-
- //*****************************************************************************
- //
- // misc to do before coordinator starts a subprocess
- //
- //*****************************************************************************
-
- - miscPrep2
- {
- int i = 0;
-
- [[theAnimator startAnimTimer] setStandbyGate:NO];
-
- [linkMenuButton setEnabled:NO]; // disable link button
- [dial setEnabled:NO]; // disable dial button
- [theOpenButton setEnabled:NO]; // disable the open doc button
- while(i < 3)
- { // erase captured str's array
- if(capturedStr[i])
- free(capturedStr[i]);
- capturedStr[i++] = NULL; // blank, for next invocation
- }
- linkStg = 0; // prevent stages in link process from getting called twice
-
- // setup and load our keyword's hashtable
- if(strHashTable)
- free(strHashTable);
- strHashTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"i"];
- for(i = 0; i < 2; i++)
- {
- numEntries[i] = i;
- [strHashTable insertKey:NXGetDefaultValue([NXApp appName], cList[i+1])
- value:&numEntries[i]];
- }
- for(i = 0; i < 4; i++)
- {
- numEntries[i + 2] = i + 2;
- [strHashTable insertKey:NXGetDefaultValue([NXApp appName], rfList[i])
- value:&numEntries[i + 2]];
- }
- numEntries[6] = 6;
- [strHashTable insertKey:"address" value:&numEntries[6]];
- numEntries[7] = 7;
- [strHashTable insertKey:"remote" value:&numEntries[7]];
-
- return self;
- }
-
- @end
- @implementation Coordinator
-
- //************************ Subprocess Delegation ****************************** //*****************************************************************************
- //
- // recieves output from subprocess
- // canonicalizes output stream into lines
- //
- //*****************************************************************************
-
- - subprocessOutput:(char *)buffer
- {
- static char strbuf[132];
- static int strpos = 0;
-
- while(*buffer)
- { // cr/lf delimit lines and we do not exceed strbuf size
- if((*buffer != '\n' && *buffer != '\r') && strpos < 128)
- {
- strbuf[strpos++] = *buffer++;
- strbuf[strpos] = '\0';
- }
- else
- {
- while((*buffer == '\n' || *buffer == '\r') && (strpos < 130))
- strbuf[strpos++] = *buffer++;
- strbuf[strpos] = '\0';
- [self analyzeBuffer:strbuf];
- strpos = 0;
- }
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // - captures certain keywords as status and info markers
- // - calls gotIt, displayLinkStatus methods when link is established
- // - sends data stream to diagnostics window and comments to status
- //
- //*****************************************************************************
-
- - analyzeBuffer:(char *)buffer
- {
- char *str, delim[] = {" \n\r^/"}, delim2[] = {"\n\r^"}, *argString = NULL;
- int *cntr;
-
- if(argString != NULL)
- free(argString);
- argString = NXCopyStringBuffer(buffer);
- [commandView appendString:buffer]; // send buffer to diag win
- str = strtok(argString, delim); // Parse string and test it
- while(str != NULL)
- {
- if(*str == '#') // comments will be displayed in status panel
- {
- if(str = strtok(NULL, delim2))
- {
- if(strlen(str) > 3)
- [statusView setStringValue:[self localString:str]];
- }
- }
- else
- {
- if ([strHashTable isKey:str] == YES) // if str is in hash table
- { // we have caught a keyword
- cntr = [strHashTable valueForKey:str];
- switch(*cntr)
- {
- case 2: // redial?
- case 3: // Persistent connect
- case 4: // Fail connect
- case 5: // LCP terminate
- if((strcmp(NXGetDefaultValue([NXApp appName],
- rsList[*cntr - 2]),"YES") == 0) // sw "ON"?
- && (lastCall[0] != '\0'))
- [self perform:@selector(redial:) with:self
- afterDelay:backOffDelay cancelPrevious:YES];
- else
- [self UnLink:nil]; // if redial off, unlink
- break;
-
- case 0: // baud str caught
- if((str = strtok(NULL, delim)) &&
- (capturedStr[0] == NULL))
- [self connectedAt:str];
- break;
-
- case 1: // the link is up
- if(linkStg < 4) // if ivar is >, ppp
- {
- [self gotIt]; // may be sending
- linkStg = 4; // keyword twice
- }
- break;
-
- case 6: // local address str caught
- if((str = strtok(NULL, delim)) && (linkStg < 5))
- {
- capturedStr[1] = NXCopyStringBuffer(str);
- linkStg = 5;
- }
- break;
-
- case 7: // display addresses
- if(linkStg < 6)
- {
- if((str = strtok(NULL, delim)) != NULL)
- {
- if((str = strtok(NULL, delim)) != NULL)
- {
- if((str = strtok(NULL, delim)) != NULL)
- {
- capturedStr[2] =
- NXCopyStringBuffer(str);
- [self displayLinkStatus];
- }
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
- }
- str = strtok(NULL, delim);
- }
-
- return self;
- }
- //************************************************************************
- //
- // Called when subprocess has terminated
- //
- //************************************************************************
-
- - subprocessDone
- {
- [theTimer stopTimer];
- if(theGateServer)
- [theGateServer free];
- theGateServer = nil;
- [theSubprocess free];
- theSubprocess = nil;
- if(userWantsTermination) // end only if user chose too (not subP fail)
- [NXApp terminate:self];
- else // if not exiting
- [theAnimator startAnimTimer]; // cycle thru animation
-
- return self;
- }
- //*****************************************************************************
- //
- // return our string table (contains key->value localization pairs)
- //
- //*****************************************************************************
-
- - stringTable;
- {
- return stringTable;
- }
- //*****************************************************************************
- //
- // localize error messages using stringTable as appropriate, displays
- // the message in an alert panel
- //
- //*****************************************************************************
-
- - showAlert:(const char *)errorString
- {
- NXRunAlertPanel(0, [self localString:errorString],
- [stringTable valueForStringKey:"OK"], NULL, NULL);
-
- return self;
- }
- //*****************************************************************************
- //
- // localize string messages using stringTable as appropriate
- //
- //*****************************************************************************
-
- - (const char *)localString:(const char *)aString
- {
- const char *returnedString;
-
- if (returnedString = [stringTable valueForStringKey:aString])
- return returnedString;
-
- return aString;
- }
- //*****************************************************************************
- //
- // Called when link is established
- //
- //*****************************************************************************
-
- - gotIt
- {
- [theAnimator removeTimedEntry];
- // ppp is up, play snd for me
- if(strcmp(NXGetDefaultValue([NXApp appName],"sound"), "YES") == 0)
- [[[Sound findSoundFor: "majestic"] play: nil] free];
- [theTimer Fire:self];
- if(!onImage)
- onImage = [NXImage findImageNamed:"g4"];
- [theIconView setImage:onImage];
- [statusView setStringValue:[self localString:"pppup"]];
- // if auto hide switch is set wait 5 sec before hiding
- if(strcmp(NXGetDefaultValue([NXApp appName], "autoHide"),"YES") == 0)
- [NXApp perform:@selector(hide:) with:self afterDelay:5000
- cancelPrevious:NO];
-
- return self;
- }
- //*****************************************************************************
- //
- // registers connection speed
- //
- //*****************************************************************************
-
- - connectedAt:(const char *)speed
- {
- strncpy(Path, [stringTable valueForStringKey:"connectAt"], MAXPATHLEN);
- strncat(Path, speed, MAXPATHLEN - strlen(Path));
- capturedStr[0] = NXCopyStringBuffer(Path);
- [connectionSpeedField setStringValue:capturedStr[0]];
-
- return self;
- }
- //*****************************************************************************
- //
- // displays captured info regarding current ppp session
- //
- //*****************************************************************************
-
- - displayLinkStatus
- {
- if(capturedStr[0] != NULL) // in case we man dialed
- { // we will not know connect speed
- [commandView appendString:"\n#################################\n"];
- [commandView appendString:"####\n"];
- [commandView appendString:"#### "];
- [commandView appendString:capturedStr[0]];
- }
- else
- [commandView appendString:"\n#################################"];
- [commandView appendString:"\n####\n"];
- [commandView appendString:[stringTable valueForStringKey:"localIP"]];
- [commandView appendString:capturedStr[1]];
- [localIPField setStringValue:capturedStr[1]];
- [commandView appendString:"\n####\n"];
- [commandView appendString:[stringTable valueForStringKey:"remoteIP"]];
- [commandView appendString:capturedStr[2]];
- [commandView appendString:"\n####"];
- [remoteIPField setStringValue:capturedStr[2]];
- [commandView appendString:"\n#################################\n"];
- linkStg = 6; // ppp link is up, set ivar
- [iTimer pppstats:commandView]; // run pppstats w/view
-
- return self;
- }
- //*********************** Application Object Delegation ***********************
- //*****************************************************************************
- //
- // setup defaults data base cache before app is init'd
- //
- //*****************************************************************************
-
- - appWillInit:sender
- {
- static NXDefaultsVector myDefaults = { // setup defaults database
- {DISPLAYD, "YES"}, // display diagnostics window
- {DISPLAYS, "YES"}, // display status window
- {"autoLaunch", "NO"},
- {"autoHide", "YES"}, // auto hide upon link
- {"autoRedial", "YES"},
- {"PersistCon", "YES"},
- {"FailRedial", "YES"}, // redial if a Fail occurs
- {"LCPterminate", "YES"}, // redial if lcp termination occurs
- {"Fail", "Exit."},
- {"reDial", "Failed"},
- {"Persist", "down"}, // persistent connect trigger
- {"LCPterm", "terminated."}, // lcp termination trigger
- {"DispPPP", "YES"}, // display pppstats
- {DISPLAYT, "YES"}, // display toolbar
- {"DoD", "NO"}, // dial on demand
- {USEFIFO, "YES"}, // use a FIFO for IPC w/pppd?
- {"sound", "YES"}, // play sound
- {AITIMER, "YES"}, // icon displayed online time
- {REDBOFF, "YES"}, // backoff on failed redials?
- {"iTimeout", "Off"}, // inactivity unlink's us
- {"preTimeout", "YES"}, // inactivity unlink's us
- {"iTimeThreshold", "0"}, // inactivity threshold
- {SELCELL, "0"}, // cell selected in hotList
- {BROWSERHT, "999.0"}, // ht of browser in hotList
- {ADDRESSHT, "999.0"}, // ht of address in hotList
- {FIRSTTIME, "YES"}, // first time thru?
- {"options", "/etc/ppp/options"},
- {"ip-down", "/etc/ppp/ip-down"},
- {"ip-up", "/etc/ppp/ip-up"},
- {"resolv", "/etc/resolv.conf"},
- {"syslog", "/etc/syslog.conf"},
- {"messages", "/usr/adm/messages"},
- {"rc", "/etc/rc.local"},
- {"remote", "/etc/remote"},
- {"locFIFO", "/usr/adm/ppp2.2.debug"}, // pref form start
- {"comLine", "/usr/local/bin/pppd -detach"},
- {HLLIST, "/"},
- {"BaudStr", "CARRIER"}, // pref form end
- {"LinkUp", "local"}, // Link is up trigger
- {DIALINIT, "ATZ&D0L3"}, // modem init str for manual Dial
- {"dialPrefix", "ATD"}, // modem AT command prefix for dialing
- {MODEMPORT, "cufa"}, // modem port, used in releasing locks
- {"path", "/"}, // path for .Gate documents
- {"lastNumDialed", "8675309"}, // default man dial number
- {"savedTime", "000000000000"}, // save time used this mo
- {"monthTime", "000000000000"}, // save mo,yr of this ses'n
- {"preMonthTime", "000000000000"}, // save previous mo,yr
- {NULL}}; // make local cache of ddb
- NXRegisterDefaults([NXApp appName], myDefaults);
-
- return self;
- }
- //*****************************************************************************
- //
- // standard init
- //
- //*****************************************************************************
-
- - appDidInit:sender
- {
- time_t waitTime; // time to delay
-
- time(<ime); // Get time and place in time_t
- if(strcmp(NXGetDefaultValue([NXApp appName], USEFIFO), "YES") == 0)
- [self syslogdReset]; // reset the syslogd daemon
-
- // setup appIcon for animation
- theAnimator = [[Animator alloc] init]; // get appIcon window
- theIconView = [theAnimator iconView];
- timeCell = [theIconView getTextCell]; // return the iconView's textCell
-
- if(strcmp(NXGetDefaultValue([NXApp appName], FIRSTTIME),"YES") == 0)
- { // if first time this version was launched
- [self showInfo:self];
- if(!NXWriteDefault([NXApp appName], FIRSTTIME, "NO"))
- NXRunAlertPanel(0,
- [stringTable valueForStringKey:"ddbWriteError"],
- [stringTable valueForStringKey:"OK"],
- NULL,
- NULL);
- }
- [NXApp loadNibSection:"StatusWindow.nib" owner:self withNames:NO];
- if(strcmp("YES", NXGetDefaultValue([NXApp appName], DISPLAYS)) == 0)
- [statusWin makeKeyAndOrderFront:self]; // show status panel
-
- [NXApp loadNibSection:"DiagWindow.nib" owner:self withNames:NO];
- [diagWin setFrameUsingName:[diagWin title]]; // remem sz,loc
- [diagWin setFrameAutosaveName:[diagWin title]];
-
- if(strcmp("YES", NXGetDefaultValue([NXApp appName], DISPLAYT)) == 0)
- [self toolBar:self]; // show toolbar if set
-
- if(strcmp("YES", NXGetDefaultValue([NXApp appName], AITIMER)) == 0)
- appIconTime = YES; // show online time in app icon
-
- if(strcmp("YES", NXGetDefaultValue([NXApp appName], REDBOFF)) == 0)
- backOffDefault = backOffDelay = BDEF; // redial delay backoff on
-
- // setup Inactivity timeout and pppstats controller
- iTimer = [[InactivityTimer allocFromZone:[self zone]] init];
-
- if(strcmp(NXGetDefaultValue([NXApp appName],"NXAutoLaunch"),"YES") == 0)
- { // if app was dock autoLaunched
- waitTime = ltime + 2; // delay for X sec so that syslogd can sync
- while(ltime < waitTime) // ltime ivar is set in syslogReset method
- {time(<ime);}
- }
- theTimer = [[Timer allocFromZone:[self zone]] init];
- // If we weren't asked to open any documents at launch time, then
- // we were launched by double clicking on the application instead
- // of a document. If so check whether we should auto-launch w/def's
- if(!NXGetDefaultValue([NXApp appName], "NXOpen") &&
- !NXGetDefaultValue([NXApp appName], "NXOpenTemp") &&
- !NXGetDefaultValue([NXApp appName], "NXServiceLaunch"))
- {
- if(strcmp(NXGetDefaultValue([NXApp appName], "autoLaunch"),"YES") == 0)
- [self Link:self];
- }
- [self DialOnDemand]; // prepare for dial on demand if set
-
- return self;
- }
- //*****************************************************************************
- //
- // redial
- //
- //*****************************************************************************
-
- - redial:sender
- { // only allow a redial if user has not stopped linking
- if((strcmp([[[NXApp mainMenu] findCellWithTag:2] title],
- [[NXApp delegate] localString:"Disconnect"]) == 0) &&
- [[[NXApp mainMenu] findCellWithTag:2] isEnabled] && (sender))
- {
- [self UnLink:nil];
- if([self runScript:"preLink"])
- { // back off in multiples of 2
- backOffDelay *= 2;
- [self perform:@selector(resetDelay:) with:self
- afterDelay:(backOffDelay + 1000) cancelPrevious:YES];
- [self linkWithFile:lastCall];
- }
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // reset the backoff delay
- //
- //*****************************************************************************
-
- - resetDelay:sender
- { // eliminate any pending redials
- [self perform:@selector(redial:) with:nil afterDelay:0 cancelPrevious:YES];
- if ([sender isKindOf:[Matrix class]])
- {
- if((BOOL)[[sender selectedCell] intValue])
- backOffDefault = BDEF; // redial delay backoff on
- else
- backOffDefault = 0;
- }
- backOffDelay = backOffDefault;
-
- return self;
- }
- //*****************************************************************************
- //
- // This method is performed whenever a user double-clicks on an icon in
- // the Workspace Manager representing a Gate program document.
- //
- // Brings up the gate doc editor which can edit or link using the doc
- //
- //*****************************************************************************
-
- - (int)app:sender openFile:(const char *)path type:(const char *)type
- {
- [theGateDocEditor editGateDoc:path];
-
- return 1;
- }
- //*****************************************************************************
- //
- // invoked immediately after app is hidden and unhidden respectively
- //
- // the following two methods are implemented to produce
- // normal main window/menu app behavior when toolBar is open
- //
- //******************************************************************************
- - appDidHide:sender
- {
- [[NXApp mainMenu] close]; // close the main menu
-
- return self;
- }
-
- - appDidUnhide:sender
- {
- [[NXApp mainMenu] makeKeyAndOrderFront:self];
-
- return self;
- }
- //*****************************************************************************
- //
- // Instantantiates the subprocess object which exec's pppd
- //
- //*****************************************************************************
-
- - linkWithFile:(const char *)path
- {
- char commandLine[MAXPATHLEN + 1];
-
- [self miscPrep2]; // misc initialization's
- if(strcmp(NXGetDefaultValue([NXApp appName], DISPLAYD),"YES") == 0)
- [diagWin makeKeyAndOrderFront:self]; // show diagnostics win
-
- strncpy(commandLine, NXGetDefaultValue([NXApp appName], "comLine"),
- MAXPATHLEN);
- commandLine[MAXPATHLEN-1] = 0;
- if(path == NULL)
- {
- lastCall[0] = '\0';
- if([hotListDelegate selGateDocOptionsPath] == NULL)
- commandLine[0] = '\0';
- else // if hotlist points to valid
- {
- strncat(commandLine, " file ", MAXPATHLEN - strlen(commandLine));
- strncat(commandLine, [hotListDelegate selGateDocOptionsPath],
- MAXPATHLEN - strlen(commandLine));
- strncpy(BPath,[hotListDelegate selGateDocOptionsPath], MAXPATHLEN);
- [providerField setStringValue:[self localString:"manDial"]];
- }
- }
- else
- {
- strcpy(lastCall, path); // stores path of last invocation
- if(strstr(path, "GateKeeper.app") == NULL)
- [providerField setStringValue:[self extractName:path]];
- else
- [providerField setStringValue:[self localString:"gkDefault"]];
- [statusView setStringValue:[self localString:"connecting"]];
- if((strlen([[NXBundle mainBundle] directory]) + 45 +
- (2 * strlen(path)) + strlen(commandLine)) < MAXPATHLEN)
- { // if we won't overrun buffer
- strcat(commandLine, " file ");
- strcat(commandLine, path);
- strcat(commandLine, OPTION); // options file name wrapper
- strcat(commandLine, " connect \"");
- strcat(commandLine, [[NXBundle mainBundle] directory]);
- strcat(commandLine, "/chat -v -f ");
- strcat(commandLine, path);
- strcat(commandLine, PPPUP); // pppup file name wrapper
- strcat(commandLine, "\"");
- }
- else
- perror("command line is longer than MAXPATHLEN");
- strncpy(BPath, path , MAXPATHLEN);
- strncat(BPath, OPTION, MAXPATHLEN - strlen(BPath)); // options
- }
- if(commandLine[0] != '\0') // if we have a valid commline
- {
- [linkMenuButton setEnabled:YES]; // enable unlink button
- [linkMenuButton setTitle:[self localString:"Disconnect"]];
- [linkMenuButton setAction:@selector(UnLink:)];
- [statusButton setTitle:[self localString:"Disconnect"]];
- [statusButton setAction:@selector(UnLink:)];
- if([iTimer posNonInter])
- [commandView appendString:
- "Dial on demand triggered ppp session\n"];
- if([self debugFlag:BPath])
- { // if debug sw set in options disg commandline
- [commandView appendString:commandLine];
- [commandView appendString:"\n\r"];
- }
- theSubprocess = [[Subprocess alloc] init:commandLine withDelegate:self
- andStdErr:YES];
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // Use terminal to do a manual link
- //
- //*****************************************************************************
-
- - Dial:sender
- {
- if((strcmp([linkMenuButton title], [self localString:"Connect"]) == 0) &&
- [linkMenuButton isEnabled] && [self runScript:"preLink"])
- {
- [self miscPrep2]; // misc initialization's
- [iTimer setPosNonInter:NO]; // user interactive session
- if(!theGateServer) // create distributed Obj server
- theGateServer = [[DOserver alloc] init];
- [theGateServer setDelegate:self];
- GateConnection = [NXConnection registerRoot: theGateServer
- withName:"GateKeeperServer"]; // DO name of server
- [GateConnection runFromAppKit]; // listen for DO messages from appKit
- if(![[NXBundle mainBundle] getPath:Path forResource:"MODEM"
- ofType:NULL])
- [self showAlert:"Error getting path for MODEM file"];
- [[Application workspace] openFile:Path withApplication:"Terminal"];
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // Called: when menu item link is pressed, when DNS triggers us.
- // Calls app:sender
- //
- //*****************************************************************************
-
- - Link:sender
- {
- if((strcmp([linkMenuButton title], [self localString:"Connect"]) == 0) &&
- [linkMenuButton isEnabled] && [self runScript:"preLink"])
- {
- if(!sender) // DNS triggered session,
- [iTimer setPosNonInter:YES]; // possibly non-interactive
- else
- [iTimer setPosNonInter:NO]; // user interactive session
- [hotListDelegate playLink]; // selected in the HotList to launch pppd
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // Called when menu item Unlink is pressed.
- //
- //*****************************************************************************
-
- - UnLink:sender
- {
- if([self runScript:"preUnLink"])
- {
- if(theSubprocess && [theSubprocess respondsTo:@selector(terminate:)])
- [theSubprocess terminate:sender];
- [[theAnimator setOpenGate:YES] setStandbyGate:YES];
- [iTimer pppstatsReset]; // disable pppstats
- [timeCell setStringValue:" "];
- [linkMenuButton setEnabled:YES]; // enable unlink button
- [linkMenuButton setTitle:[self localString:"Connect"]];
- [linkMenuButton setAction:@selector(Link:)];
- [statusButton setTitle:[self localString:"Connect"]];
- [statusButton setAction:@selector(Link:)];
- [theOpenButton setEnabled:YES]; // enable the open doc button
- [dial setEnabled:YES]; // enable dial button
- [statusView setStringValue:[self localString:"pppdn"]];
- [connectionSpeedField setStringValue:" "];
- [timeField setStringValue:" "];
- [providerField setStringValue:" "];
- [localIPField setStringValue:" "];
- [remoteIPField setStringValue:" "];
- [self namedDod]; // kill/restart named to dump cache
- }
- if(sender)
- [self resetDelay:self];
-
- return self;
- }
- //*****************************************************************************
- //
- // run the preLink or preUnLink scripts, proceed if exit status true
- //
- //*****************************************************************************
-
- - runScript:(const char *)type
- {
- id exitStatus = self;
- int fd;
-
- strncpy(Path, [[NXBundle mainBundle] directory], MAXPATHLEN);
- strncat(Path, "/", MAXPATHLEN - strlen(Path));
- strncat(Path, type, MAXPATHLEN - strlen(Path));
- if(fd = open(Path, O_RDONLY) != -1) // if script exists
- {
- close(fd);
- if(system(Path) != 0) // exec script, test exit
- exitStatus = nil;
- strcpy(Path, type);
- if(!exitStatus)
- strcat(Path," script exit status prevents requested action\n");
- else
- strcat(Path, " script executed sucessfully\n");
- [commandView appendStringUseFixedFont:Path];
- }
-
- return exitStatus;
- }
- //*****************************************************************************
- //
- // we can always edit another gate doc
- //
- //*****************************************************************************
-
- - (BOOL)appAcceptsAnotherFile:sender
- {
- return YES;
- }
- //****************************************************************************
- //
- // termination is allowed only if the user has selected it, subprocess
- // failure should not cause GateKeeper to terminate
- //
- //****************************************************************************
-
- - terminate:sender
- {
- userWantsTermination = YES;
-
- return self;
- }
- //****************************************************************************
- //
- // termination is imminent
- //
- //****************************************************************************
-
- - appWillTerminate:sender
- {
- [theSubprocess terminate:sender];
- [theAnimator removeTimedEntry];
- [self namedReset:"/usr/etc/named"]; // replace our named with system's
- [hotListDelegate appWillTerminate];
-
- return self;
- }
- //*****************************************************************************
- //
- // show the info panel
- //
- //*****************************************************************************
-
- - showInfo:sender
- {
- if(!infoPanel)
- [NXApp loadNibSection:"InfoPanel.nib" owner:self withNames:NO];
- [infoPanel center];
- [infoPanel makeKeyAndOrderFront:self];
-
- return self;
- }
- //****************************************************************************
- //
- // show preferences panel
- //
- //****************************************************************************
-
- - preferences:sender
- {
- if(!prefPanel)
- [NXApp loadNibSection:"Preferences.nib" owner:self withNames:NO];
- [prefPanel makeKeyAndOrderFront:self];
-
- return self;
- }
- //************************************************************************
- //
- // show NXHelpPanel
- //
- //************************************************************************
-
- - showHelpPanel:sender
- {
- if(!helpPanel)
- helpPanel = [NXHelpPanel new];
- [helpPanel display];
- [helpPanel makeKeyAndOrderFront:self];
-
- return self;
- }
- //************************************************************************
- //
- // display the Status panel
- //
- //************************************************************************
-
- - showStatusPanel:sender
- {
- if(!NXWriteDefault([NXApp appName], DISPLAYS, "YES"))
- [self showAlert:"ddbWriteError"];
-
- return [statusWin makeKeyAndOrderFront:self];
- }
- //*****************************************************************************
- //
- // display the Diagnostics window
- //
- //*****************************************************************************
-
- - showDiagWin:sender
- {
- if(!NXWriteDefault([NXApp appName], DISPLAYD, "YES"))
- [self showAlert:"ddbWriteError"];
-
- return [diagWin makeKeyAndOrderFront:self];
- }
- //************************************************************************
- //
- // show the timer
- //
- //************************************************************************
-
- - showTimerPanel:sender
- {
- return [theTimer showTimerPanel:self];
- }
- //*****************************************************************************
- //
- // called by timer in order to pass us appIcon time string
- //
- // also used in determining inactivity timeout (since this is called
- // once per minute during ppp sessions).
- //
- //*****************************************************************************
-
- - showMenuTimer:(char *)buffer
- {
- if(appIconTime)
- [timeCell setStringValue:buffer];
- [timeField setStringValue:buffer];
- [theIconView setImage:onImage];
- [iTimer inactivityTimeout];
-
- return self;
- }
- //*****************************************************************************
- //
- // set inactivity timer's timeout Ivar and write its value to ddb
- //
- //*****************************************************************************
-
- - setTimeout:(int)minTillTimeout
- {
- [iTimer setTimeout:minTillTimeout];
-
- return self;
- }
- //*****************************************************************************
- //
- // enable/disable display of online time in app icon
- //
- //*****************************************************************************
-
- - setAppIconTimer:(BOOL)onOff
- {
- appIconTime = onOff;
-
- return self;
- }
- //*****************************************************************************
- //
- // return a pointer to the hotlist window's delegate
- //
- //*****************************************************************************
-
- - hotListDelegate
- {
- return hotListDelegate;
- }
- //*****************************************************************************
- //
- // tell browser to update its data from its delegate
- //
- //*****************************************************************************
-
- - updateBrowser:sender
- {
- return [hotListDelegate loadBrowser];
- }
- //************************************************************************
- //
- // extracts the Gate doc name from its path
- //
- //************************************************************************
-
- - (const char *)extractName:(const char *)aPath
- {
- char *ptr;
-
- strcpy(Path, aPath);
- ptr = Path + strlen(Path) - 1;
- while(*ptr != '.' && *ptr)
- ptr--;
- *ptr-- = '\0';
- while(*ptr != '/' && *ptr)
- ptr--;
- ++ptr;
-
- return ptr;
- }
- //************************************************************************
- //
- // returns whether a Gate doc may be opened or edited by real user
- //
- //************************************************************************
-
- - readable:(const char *)nameOfFile
- {
- FILE *fp;
-
- if ((fp = fopen(nameOfFile, "r+")) == NULL)
- [self showAlert:"Unable to open Gate doc"];
- else
- {
- if(readable(fileno(fp)))
- {
- fclose(fp);
- return self; // we have permission
- }
- [self showAlert:"Access to Gate doc denied"];
- fclose(fp);
- }
-
- return nil; // we do not have permission
- }
- //*****************************************************************************
- //
- // returns the Gate doc options editor
- //
- //*****************************************************************************
-
- - optionsEditor
- {
- if(!theOptionsEditor)
- theOptionsEditor = [[OptionsEditor alloc] init];
-
- return theOptionsEditor;
- }
- //*****************************************************************************
- //
- // returns the state of the debug flag in an options file
- //
- //*****************************************************************************
-
- - (BOOL)debugFlag:(const char *)optionFile
- {
- return [[[self optionsEditor] parseOptions:optionFile] debug];
- }
- //*****************************************************************************
- //
- // show the Tool Bar
- //
- //*****************************************************************************
-
- - toolBar:sender
- {
- if(!NXWriteDefault([NXApp appName], DISPLAYT, "YES"))
- [self showAlert:"ddbWriteError"];
- if(!toolBar)
- [NXApp loadNibSection:"ToolBar.nib" owner:self withNames:NO];
- [toolBar makeKeyAndOrderFront:self];
-
- return toolBar;
- }
- //************************************************************************
- //
- // return the app icons view
- //
- //************************************************************************
-
- - appIconView
- {
- return theIconView; // enable link button
- }
- //************************************************************************
- //
- // called by DO server when remote manual Dial Tool's ports are
- // invalidated
- //
- //************************************************************************
-
- - DOFinished
- {
- return [self UnLink:self]; // enable link button
- }
- //************************************************************************
- //
- // free simply gets rid of everything we created
- // This is how nice objects clean up.
- //
- //************************************************************************
-
- - free
- {
- [timeCell free];
- if(onImage)
- [onImage free];
- if(toolBar)
- [toolBar free];
- if(iTimer)
- [iTimer free];
-
- return [super free];
- }
- //*****************************************************************************
- //
- // Attempt to reset syslogd daemon. Failing that, try starting it.
- //
- //*****************************************************************************
-
- - syslogdReset
- {
- FILE *ff;
- int pid;
-
- if((ff = fopen( "/etc/syslog.pid", "r")) != NULL)
- {
- if( fscanf( ff, "%d", &pid) < 1)
- perror("Unable to read pid from etc/syslog.pid\n");
- else
- {
- if( kill( pid, SIGHUP) != -1) // tell syslogd to reconfigure
- {
- fclose( ff);
-
- return self; // report success
- }
- else // if app was not dock autoLaunched
- if(strcmp(NXGetDefaultValue(
- [NXApp appName],"NXAutoLaunch"),"NO") == 0)
- perror("error reconfiguring syslogd");
- }
- }
- else
- perror("Unable to open /etc/syslog.pid\n");
-
- return [self syslogdRun]; // failed to reconfig so restart syslogd
- }
- //*****************************************************************************
- //
- // Terminante and then run the syslogd daemon
- //
- //*****************************************************************************
-
- - syslogdRun
- {
- int pid;
- FILE *ff;
-
- if((ff = fopen( "/etc/syslog.pid", "r")) != NULL)
- {
- if( fscanf( ff, "%d", &pid) < 1)
- perror("Unable to read pid from etc/syslog.pid\n");
- else
- if( kill( pid, SIGTERM) == -1)
- {
- if(strcmp(NXGetDefaultValue(
- [NXApp appName],"NXAutoLaunch"),"NO") == 0)
- perror("error killing syslogd");
- }
- }
- switch (pid = vfork()) // create new process
- {
- case -1: // error
-
- perror("Error during vfork syslogdReset.");
- return self;
-
- case 0: // child -- Vfork returns 0 in the child's context
-
- execl("/usr/etc/syslogd", "syslogd", 0);
- perror("vfork error restarting syslogd");
- exit(1);
-
- default: // parent -- vfork returns pid of the child
-
- break;
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // prepare ourself to be triggered by named when dial on demand is
- // necessary
- //
- //*****************************************************************************
-
- - DialOnDemand
- {
- port_t server_port;
- kern_return_t r;
-
- // if dial on demand is "ON"
- if(strcmp("YES", NXGetDefaultValue([NXApp appName], "DoD")) == 0)
- {
- // allocate a port for this task, ret in arg 2
- r = port_allocate(task_self(), &server_port);
- if (r != KERN_SUCCESS)
- {
- mach_error("port_allocate failed", r);
- exit(1);
- } // Register with the Network Name Server.
- r = netname_check_in(name_server_port, GK_DNS_SERVER, PORT_NULL,
- server_port);
- if (r != KERN_SUCCESS)
- {
- mach_error("netname_check_in failed", r);
- exit(1);
- }
- // create dial on demand server thread and detach it
- cthread_detach(cthread_fork((cthread_fn_t)server_loop,
- (any_t)server_port));
- [self namedDod]; // replace named with dial on demand trigger named
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // Attempt to kill and restart named daemon. Resets RR's cache.
- //
- //*****************************************************************************
-
- - namedReset:(const char *)buffer
- {
- FILE *ff;
- int pid;
- // if dial on demand is "ON"
- if(strcmp("YES", NXGetDefaultValue([NXApp appName], "DoD")) == 0)
- {
- if((ff = fopen( "/etc/named.pid", "r")) != NULL)
- {
- if( fscanf( ff, "%d", &pid) < 1)
- perror("Unable to read pid from etc/named.pid\n");
- else
- {
- if( kill( pid, SIGTERM) == -1) // kill named
- perror("error killing named");
- }
- }
- else
- perror("Unable to open /etc/named.pid\n");
- fclose( ff);
- system(buffer); // start GateKeeper named
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // replace the system named with our own which will inform us when a
- // dial on demand is necessary
- //
- //*****************************************************************************
-
- - namedDod
- {
- if(!strcpy(Path, [[NXBundle mainBundle] directory])) // app's home dir
- [self showAlert:"Error getting mainbundle path"];
- else
- {
- strcat(Path,"/named");
- [self namedReset:Path]; // kill named and replace with our own
- }
-
- return self;
- }
- //*****************************************************************************
- //
- // search /etc/syslog.conf to find the location of the named pipe used
- // in recieving the output from pppd/syslog
- //
- //*****************************************************************************
-
- - fifo
- {
- static char del1[] = {". =:|\t\r\n"}, del2[] = {" \t\r\n"};
- char *fifoName = NULL;
-
- if(!Parser)
- Parser = [[Parse alloc] init]; // create parser to find port
- [[Parser setKey1:"local2"] setKey2:"debug"]; // set search pattern
- [[Parser setDelim1:del1] setDelim2:del2]; // and delimiters
-
- if(fifoName = [Parser parseFile:"/etc/syslog.conf"])
- {
- if(!NXWriteDefault([NXApp appName], "locFIFO", fifoName))
- NXRunAlertPanel(0,
- [stringTable valueForStringKey:"ddbWriteError"],
- [stringTable valueForStringKey:"OK"],
- NULL,
- NULL);
- free(fifoName);
- }
- else
- [self showAlert:"FIFO Path Error"];
-
- return self;
- }
- //*****************************************************************************
- //
- // checks the mail queue for mail awaiting delivery
- //
- //*****************************************************************************
-
- - (BOOL)mailInQueue
- {
- int eCntr = 0;
- struct direct *dirp;
- DIR *dp;
- BOOL mail = NO;
-
- if ((dp = opendir("/usr/spool/mqueue")) != NULL)
- {
- while ((dirp = readdir(dp)) && eCntr < 3) // read dir and cnt entries
- {
- if(*dirp->d_name != '.') // don't count if sys file
- eCntr++;
- }
- if(eCntr > 2)
- mail = YES;
- closedir(dp);
- }
- else
- [self showAlert:"Error opening Mail queue directory"];
-
- return mail;
- }
- //************** Diagnostics Window delegate methods **************************
- //*****************************************************************************
- //
- // called whenever the user minituriazes our Diagnostics window.
- //
- //*****************************************************************************
-
- - windowWillMiniaturize:sender toMiniwindow:miniwindow
- {
- return [sender setMiniwindowIcon:"miniWinIcon"];
- }
- //*****************************************************************************
- //
- // called whenever the user closes our Diagnostics window.
- //
- //*****************************************************************************
-
- - windowWillClose:sender
- {
- if(![sender isKindOf:[Panel class]]) // simple test to see if diag
- { // win is what is being closed
- if(!NXWriteDefault([NXApp appName], DISPLAYD, "NO"))
- [self showAlert:"ddbWriteError"];
- }
-
- return self;
- }
-
- @end
-
- //*****************************************************************************
- //
- // c thread loop which listens for RPC telling us to link
- //
- //*****************************************************************************
-
- any_t server_loop(any_t port)
- {
- struct message msg, reply;
- kern_return_t ret;
-
- while (TRUE)
- {
- /* Receive a request from a client. */
- msg.head.msg_local_port = (port_t)port;
- msg.head.msg_size = sizeof(struct message);
- ret = msg_receive(&msg.head, MSG_OPTION_NONE, 0);
- if (ret != RCV_SUCCESS) /* ignore errors */
- continue;
-
- /* Feed the request into the server. */
- (void)nsRPC_server((msg_header_t *)&msg, (msg_header_t *)&reply);
-
- /* Send a reply to the client. */
- reply.head.msg_local_port = (port_t)port;
- ret = msg_send(&reply.head, MSG_OPTION_NONE, 0);
- if (ret != SEND_SUCCESS) /* ignore errors */
- continue;
- }
- return 0;
- }
- //*****************************************************************************
- //
- // This function is called by nsRPC_server, which was created by MiG.
- // It is NOT directly called by any client process.
- //
- //*****************************************************************************
-
- kern_return_t pppUp(port_t server)
- {
- [[NXApp delegate] Link:nil];
-
- return KERN_SUCCESS;
- }
-